http://blog.csdn.net/lee_3do/article/details/39288329
回顾
我们在上面一节中讲到了SurfaceFlinger创建过程中和VSync有关的一些处理,总结起来如下图:图中红色部分涉及到了VSync信号的在系统内的传输过程,我们在这一章详细的展开说明。
向Eventhread注册一个事件的监听者——createEventConnection
在SurfaceFlinger的init函数中,我们调用了mEventQueue.setEventThread(mSFEventThread)函数,我们在前面一章中已经提到过,这个函数将SurfaceFlinger的MessageQueue真正和我们刚才创建的EventThread建立起了连接。我们来看下这段代码:
- void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
- {
- mEventThread = eventThread;
- mEvents = eventThread->createEventConnection();
- mEventTube = mEvents->getDataChannel();
- mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,
- MessageQueue::cb_eventReceiver, this);
- }
createEventConnection是将EventThread和MessageQueue建立连接的函数:
- sp<EventThread::Connection> EventThread::createEventConnection() const {
- return new Connection(const_cast<EventThread*>(this));
- }
- EventThread::Connection::Connection(
- const sp<EventThread>& eventThread)
- : count(-1), mEventThread(eventThread), mChannel(new BitTube())
- {
- }
- void EventThread::Connection::onFirstRef() {
- mEventThread->registerDisplayEventConnection(this);
- }
- status_t EventThread::registerDisplayEventConnection(
- const sp<EventThread::Connection>& connection) {
- mDisplayEventConnections.add(connection);
- mCondition.broadcast();
- }
我们看这个函数虽然传递了很多次,但是其实逻辑依然很简单易懂。其实无非是这个函数会导致一个Connection类的创建,而这个connection类会被保存在EventThread下的一个容器内。
通过createEventConnection这样一个简单的方法,我们其实就注册了一个事件的监听者,得到了发送VSYNC事件通知的BitTube,然后监控这个BitTube中的套接字,并且指定了收到通知后的回调函数,MessageQueue::cb_eventReceiver。这样一旦VSync信号传来,函数cb_eventReceiver将被调用。
等待事件
继续回到上一章的图中:
刚才我们分析了创建一个连接,SurfaceFlinger的MessageQueue注册了一个监听者到EventThread中的mDisplayEventConnections容器中,等待event事件到来时被通知。下面我们继续分析一下我们前面一章没有展开说明的另外一个函数:
EventThread中等待事件时的函数waitForEvent。
- // This will return when (1) a vsync event has been received, and (2) there was
- // at least one connection interested in receiving it when we started waiting.
- Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
- DisplayEventReceiver::Event* event)
- {
- // Here we figure out if we need to enable or disable vsyncs
- if (timestamp && !waitForVSync) {
- // we received a VSYNC but we have no clients
- // don't report it, and disable VSYNC events
- disableVSyncLocked();
- } else if (!timestamp && waitForVSync) {
- // we have at least one client, so we want vsync enabled
- // (TODO: this function is called right after we finish
- // notifying clients of a vsync, so this call will be made
- // at the vsync rate, e.g. 60fps. If we can accurately
- // track the current state we could avoid making this call
- // so often.)
- enableVSyncLocked();
- }
- // note: !timestamp implies signalConnections.isEmpty(), because we
- // don't populate signalConnections if there's no vsync pending
- if (!timestamp && !eventPending) {
- // wait for something to happen
- if (waitForVSync) {
- // This is where we spend most of our time, waiting
- // for vsync events and new client registrations.
- //
- // If the screen is off, we can't use h/w vsync, so we
- // use a 16ms timeout instead. It doesn't need to be
- // precise, we just need to keep feeding our clients.
- //
- // We don't want to stall if there's a driver bug, so we
- // use a (long) timeout when waiting for h/w vsync, and
- // generate fake events when necessary.
- bool softwareSync = mUseSoftwareVSync;
- nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
- if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
- if (!softwareSync) {
- ALOGW("Timed out waiting for hw vsync; faking it");
- }
- // FIXME: how do we decide which display id the fake
- // vsync came from ?
- mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
- mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
- mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
- mVSyncEvent[0].vsync.count++;
- }
- } else {
- // Nobody is interested in vsync, so we just want to sleep.
- // h/w vsync should be disabled, so this will wait until we
- // get a new connection, or an existing connection becomes
- // interested in receiving vsync again.
- mCondition.wait(mLock);
- }
- }
- } while (signalConnections.isEmpty());
- // here we're guaranteed to have a timestamp and some connections to signal
- // (The connections might have dropped out of mDisplayEventConnections
- // while we were asleep, but we'll still have strong references to them.)
- return signalConnections;
- }
waitForEvent是一个相当长的函数,我们上文只截取了函数的后半部分,在被删掉的前半部分中,函数主要在处理和EventThread建立起连接的客户端,也就是我们上面提到的通过createEventConnection来于EventThread建立起连接的客户端。
前半部分代码通过计算对两个变量的赋值产生了影响,timestamp非零代表有一个VSync信号需要处理,waitForVSync为true则代表有客户端在等待VSync信号。我们下面来仔细分析下后半部分的代码:
- // Here we figure out if we need to enable or disable vsyncs
- if (timestamp && !waitForVSync) {
- // we received a VSYNC but we have no clients
- // don't report it, and disable VSYNC events
- disableVSyncLocked();
- } else if (!timestamp && waitForVSync) {
- // we have at least one client, so we want vsync enabled
- // (TODO: this function is called right after we finish
- // notifying clients of a vsync, so this call will be made
- // at the vsync rate, e.g. 60fps. If we can accurately
- // track the current state we could avoid making this call
- // so often.)
- enableVSyncLocked();
- }
上面这段代码的含义其实注释里面写的很清楚,根据是否需要来决定禁用和开启VSync信号。两个分支的条件也都有注释,第一个分支的含义是收到了VSync但是却没有客户端感兴趣,这个时候我们会选择禁用VSync,另一条分支则是没有收到VSync信号但是有客户端对信号感兴趣,那么这个时候我们会开启VSync。
在上一章中我们已经提到了,真正向硬件发送开关VSync信号的命令的是EventControlThread,那么这里的disableVSyncLocked和enableVSyncLocked的原理是否和EventControlThread一致呢?我们来仔细分析一下这个函数:
- void EventThread::enableVSyncLocked() {
- if (!mUseSoftwareVSync) {//这个条件会筛掉灭屏的情况
- // never enable h/w VSYNC when screen is off
- if (!mVsyncEnabled) {
- mVsyncEnabled = true;
- mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
- mVSyncSource->setVSyncEnabled(true);
- mPowerHAL.vsyncHint(true);
- }
- }
- mDebugVsyncEnabled = true;
- }
上面函数主要调用了VSyncSource的setVSyncEnabled函数:
- virtual void setVSyncEnabled(bool enable) {
- // Do NOT lock the mutex here so as to avoid any mutex ordering issues
- // with locking it in the onDispSyncEvent callback.
- if (enable) {
- status_t err = mDispSync->addEventListener(mPhaseOffset,
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error registering vsync callback: %s (%d)",
- strerror(-err), err);
- }
- ATRACE_INT("VsyncOn", 1);
- } else {
- status_t err = mDispSync->removeEventListener(
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error unregistering vsync callback: %s (%d)",
- strerror(-err), err);
- }
- ATRACE_INT("VsyncOn", 0);
- }
- }
- status_t DispSync::addEventListener(nsecs_t phase,
- const sp<Callback>& callback) {
- return mThread->addEventListener(phase, callback);
- }
看到这里我们发现,其实所谓的disableVSyncLocked和enableVSyncLocked禁用开启VSync信号并非真的让硬件停止发送信号,只是向DispSync(里面的DispSyncThread,DispSyncThread在DispSync被创建时启动)删除和添加事件的监听者,通过添加监听者,新的监听者就可以收到来自硬件的VSync消息,而一旦删除,EventThread不再能收到消息,显然对于EventThread来说,也就禁用了VSync消息。
分析完EventThread的disableVSyncLocked和enableVSyncLocked函数,我们回到waitForEvent函数继续分析。剩下的逻辑很简单了:
- // wait for something to happen
- if (waitForVSync) {
- // This is where we spend most of our time, waiting
- // for vsync events and new client registrations.
- //
- // If the screen is off, we can't use h/w vsync, so we
- // use a 16ms timeout instead. It doesn't need to be
- // precise, we just need to keep feeding our clients.
- //
- // We don't want to stall if there's a driver bug, so we
- // use a (long) timeout when waiting for h/w vsync, and
- // generate fake events when necessary.
- bool softwareSync = mUseSoftwareVSync;
- nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
- if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
- if (!softwareSync) {
- ALOGW("Timed out waiting for hw vsync; faking it");
- }
- // FIXME: how do we decide which display id the fake
- // vsync came from ?
- mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
- mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
- mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
- mVSyncEvent[0].vsync.count++;
- }
- } else {
- // Nobody is interested in vsync, so we just want to sleep.
- // h/w vsync should be disabled, so this will wait until we
- // get a new connection, or an existing connection becomes
- // interested in receiving vsync again.
- mCondition.wait(mLock);
- }
代码不长,逻辑也很简单,这里通过mCondition.waitRelative和mCondition.wait开始等待事件的发生了。
终于分析完这里,我们已经注册好了监听者,起好了线程,开始等待VSync的到来了。我们终于可以回到最最开始的问题里面,当VSync信号发出来时,系统到底是怎么处理的?
VSync信号的处理
我们在前面一章也提到了无论是软件方式还是硬件方式,SurfaceFlinger收到VSync信号后,处理函数都是onVSyncReceived函数:
- void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
- bool needsHwVsync = false;
- {
- if (type == 0 && mPrimaryHWVsyncEnabled) {
- needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
- }
- }
- if (needsHwVsync) {
- enableHardwareVsync();
- } else {
- disableHardwareVsync(false);
- }
- }
前文中我们也说过这段代码中最重要的一个函数调用—-addResyncSample,下面本文也将从这个函数开始继续VSync的研究。
真正开始处理VSync消息——addResyncSample
- bool DispSync::addResyncSample(nsecs_t timestamp) {
- size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
- mResyncSamples[idx] = timestamp;
- if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
- mNumResyncSamples++;
- } else {
- mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
- }
- updateModelLocked();
- if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {
- resetErrorLocked();
- }
- if (runningWithoutSyncFramework) {
- // If we don't have the sync framework we will never have
- // addPresentFence called. This means we have no way to know whether
- // or not we're synchronized with the HW vsyncs, so we just request
- // that the HW vsync events be turned on whenever we need to generate
- // SW vsync events.
- return mThread->hasAnyEventListeners();
- }
- return mPeriod == 0 || mError > errorThreshold;
- }
粗略浏览下这个函数,发现前半部分其实在做一些简单的计数统计,重点实现显然是updateModelLocked函数:
- void DispSync::updateModelLocked() {
- if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
- nsecs_t durationSum = 0;
- for (size_t i = 1; i < mNumResyncSamples; i++) {
- size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
- size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
- durationSum += mResyncSamples[idx] - mResyncSamples[prev];
- }
- mPeriod = durationSum / (mNumResyncSamples - 1);
- double sampleAvgX = 0;
- double sampleAvgY = 0;
- double scale = 2.0 * M_PI / double(mPeriod);
- for (size_t i = 0; i < mNumResyncSamples; i++) {
- size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
- nsecs_t sample = mResyncSamples[idx];
- double samplePhase = double(sample % mPeriod) * scale;
- sampleAvgX += cos(samplePhase);
- sampleAvgY += sin(samplePhase);
- }
- sampleAvgX /= double(mNumResyncSamples);
- sampleAvgY /= double(mNumResyncSamples);
- mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);
- if (mPhase < 0) {
- mPhase += mPeriod;
- }
- if (traceDetailedInfo) {
- ATRACE_INT64("DispSync:Period", mPeriod);
- ATRACE_INT64("DispSync:Phase", mPhase);
- }
- mThread->updateModel(mPeriod, mPhase);
- }
- }
不得不说,前面大段的数学计算让人有些困惑,我们暂且跳过,先分析下主线流程,也就是mThread->updateModel(mPeriod, mPhase)这个调用:
DispSyncThread.updateModel的用途
- void updateModel(nsecs_t period, nsecs_t phase) {
- Mutex::Autolock lock(mMutex);
- mPeriod = period;
- mPhase = phase;
- mCond.signal();
- }
updateModel是DispSyncThread类的函数,这个函数本身代码很短,其实它的主要作用是mCond.signal发送一个信号给等待中的线程。那么究竟是谁在等待这个条件呢?
其实等待这个条件的正是DispSyncThread的循环函数:
- virtual bool threadLoop() {
- status_t err;
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- nsecs_t nextEventTime = 0;
- while (true) {
- Vector<CallbackInvocation> callbackInvocations;
- nsecs_t targetTime = 0;
- { // Scope for lock
- Mutex::Autolock lock(mMutex);
- if (mStop) {
- return false;
- }
- if (mPeriod == 0) {
- err = mCond.wait(mMutex);
- if (err != NO_ERROR) {
- ALOGE("error waiting for new events: %s (%d)",
- strerror(-err), err);
- return false;
- }
- continue;
- }
- nextEventTime = computeNextEventTimeLocked(now);
- targetTime = nextEventTime;
- bool isWakeup = false;
- if (now < targetTime) {
- err = mCond.waitRelative(mMutex, targetTime - now);
- if (err == TIMED_OUT) {
- isWakeup = true;
- } else if (err != NO_ERROR) {
- ALOGE("error waiting for next event: %s (%d)",
- strerror(-err), err);
- return false;
- }
- }
- now = systemTime(SYSTEM_TIME_MONOTONIC);
- if (isWakeup) {
- mWakeupLatency = ((mWakeupLatency * 63) +
- (now - targetTime)) / 64;
- if (mWakeupLatency > 500000) {
- // Don't correct by more than 500 us
- mWakeupLatency = 500000;
- }
- if (traceDetailedInfo) {
- ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime);
- ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
- }
- }
- callbackInvocations = gatherCallbackInvocationsLocked(now);
- }
- if (callbackInvocations.size() > 0) {
- fireCallbackInvocations(callbackInvocations);
- }
- }
- return false;
- }
大量的时间相关的计算和状态的转变我们不再深入研究,我们来看下这个线程被通知唤醒之后做的两个主要的函数的处理,gatherCallbackInvocationsLocked和fireCallbackInvocations。
gatherCallbackInvocationsLocked的代码其实很简单:
- Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
- Vector<CallbackInvocation> callbackInvocations;
- nsecs_t ref = now - mPeriod;
- for (size_t i = 0; i < mEventListeners.size(); i++) {
- nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
- ref);
- if (t < now) {
- CallbackInvocation ci;
- ci.mCallback = mEventListeners[i].mCallback;
- ci.mEventTime = t;
- callbackInvocations.push(ci);
- mEventListeners.editItemAt(i).mLastEventTime = t;
- }
- }
- return callbackInvocations;
- }
其实就是从mEventListeners取出之前注册的事件监听者,放入callbackInvocations中,等待后面的调用。至于监听者从何处而来?我们在前面已经给出了分析,在waitforevent时通过enableVSyncLocked注册的。
继续看下fireCallbackInvocations函数:
- void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
- for (size_t i = 0; i < callbacks.size(); i++) {
- callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
- }
- }`
我们目前只分析主线的走向,接下来调用了DispSyncSource的onDispSyncEvent在:
- virtual void onDispSyncEvent(nsecs_t when) {
- sp<VSyncSource::Callback> callback;
- {
- callback = mCallback;
- }
- if (callback != NULL) {
- callback->onVSyncEvent(when);
- }
- }
- void EventThread::onVSyncEvent(nsecs_t timestamp) {
- Mutex::Autolock _l(mLock);
- mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
- mVSyncEvent[0].header.id = 0;
- mVSyncEvent[0].header.timestamp = timestamp;
- mVSyncEvent[0].vsync.count++;
- mCondition.broadcast();
- }
我们看到这里mCondition.broadcas发出了命令,那么EventThread中waitforEvent的等待就会被唤醒。而一旦唤醒,我们就回到了EventThread的loop中,我们来看下代码:
- bool EventThread::threadLoop() {
- DisplayEventReceiver::Event event;
- Vector< sp<EventThread::Connection> > signalConnections;
- signalConnections = waitForEvent(&event);
- // dispatch events to listeners...
- const size_t count = signalConnections.size();
- for (size_t i=0 ; i<count ; i++) {
- const sp<Connection>& conn(signalConnections[i]);
- // now see if we still need to report this event
- status_t err = conn->postEvent(event);
- if (err == -EAGAIN || err == -EWOULDBLOCK) {
- // The destination doesn't accept events anymore, it's probably
- // full. For now, we just drop the events on the floor.
- // FIXME: Note that some events cannot be dropped and would have
- // to be re-sent later.
- // Right-now we don't have the ability to do this.
- ALOGW("EventThread: dropping event (%08x) for connection %p",
- event.header.type, conn.get());
- } else if (err < 0) {
- // handle any other error on the pipe as fatal. the only
- // reasonable thing to do is to clean-up this connection.
- // The most common error we'll get here is -EPIPE.
- removeDisplayEventConnection(signalConnections[i]);
- }
- }
- return true;
- }
这里主要就是通过conn->postEvent来分发事件:
- status_t EventThread::Connection::postEvent(
- const DisplayEventReceiver::Event& event) {
- ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
- return size < 0 ? status_t(size) : status_t(NO_ERROR);
- }
- ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
- Event const* events, size_t count)
- {
- return BitTube::sendObjects(dataChannel, events, count);
- }
其实看到这里的BitTube我们就明白了,在本文开始时候我们提到:
通过createEventConnection这样一个简单的方法,我们其实就注册了一个事件的监听者,得到了发送VSYNC事件通知的BitTube,然后监控这个BitTube中的套接字,并且指定了收到通知后的回调函数,MessageQueue::cb_eventReceiver。这样一旦VSync信号传来,函数cb_eventReceiver将被调用。
所以我们这里可以来看看MessageQueue::cb_eventReceiver函数了:
- int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
- MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
- return queue->eventReceiver(fd, events);
- }
- int MessageQueue::eventReceiver(int fd, int events) {
- ssize_t n;
- DisplayEventReceiver::Event buffer[8];
- while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
- for (int i=0 ; i<n ; i++) {
- if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
- mHandler->dispatchInvalidate();
- break;
- }
- }
- }
- return 1;
- }
我们看到收到消息之后MessageQueue对消息进行了分发,我们目前走的是dispatchInvalidate。
- void MessageQueue::Handler::dispatchInvalidate() {
- if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
- mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
- }
- }
- void MessageQueue::Handler::handleMessage(const Message& message) {
- switch (message.what) {
- case INVALIDATE:
- android_atomic_and(~eventMaskInvalidate, &mEventMask);
- mQueue.mFlinger->onMessageReceived(message.what);
- break;
- case REFRESH:
- android_atomic_and(~eventMaskRefresh, &mEventMask);
- mQueue.mFlinger->onMessageReceived(message.what);
- break;
- case TRANSACTION:
- android_atomic_and(~eventMaskTransaction, &mEventMask);
- mQueue.mFlinger->onMessageReceived(message.what);
- break;
- }
- }
- void SurfaceFlinger::onMessageReceived(int32_t what) {
- ATRACE_CALL();
- switch (what) {
- case MessageQueue::TRANSACTION:
- handleMessageTransaction();
- break;
- case MessageQueue::INVALIDATE:
- handleMessageTransaction();
- handleMessageInvalidate();
- signalRefresh();
- break;
- case MessageQueue::REFRESH:
- handleMessageRefresh();
- break;
- }
- }
到了这里,就进入了SurfaceFlinger的处理流程,我们看到对于INVALIDATE的消息,实际上系统在处理过程中实际还是会发送一个Refresh消息。
这后面的处理过程,我会在博客后面的文章中详细讲解。
总结
我们用了两小节的篇幅来讲解了VSync在android系统中的作用,生成以及传递。详细说明了从VSync软硬件的生成,一直到事件如何做为一个INVALIDATE消息传递给了Surfaceflinger处理。我们再来回顾一下整体的流程图: