Android SurfaceFlinger服务 ----- VSync信号的分发

学向勤中得,萤窗万卷书。这篇文章主要讲述Android SurfaceFlinger服务 ----- VSync信号的分发相关的知识,希望能为你提供帮助。
HWComposer模块产生VSync信号后要经过分发才能送达到关心VSync事件的模块中去。VSync信号分发大致流程为HWComposer-> SurfaceFlinger-> DispSync-> DispSyncSource-> 各个具体模块。下面具体分析下这个流程。
在上一篇文章中分析到硬件或者软件VSync信号产生时,会回调SurfaceFlinger的onVSyncReceived函数,来看看这个函数:

void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) { bool needsHwVsync = false; { // Scope for the lock Mutex::Autolock _l(mHWVsyncLock); if (type == 0 & & mPrimaryHWVsyncEnabled) { needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp); } }if (needsHwVsync) { enableHardwareVsync(); } else { disableHardwareVsync(false); } }

  • mPrimaryDispSync类型为DispSync,在构造的时候会创建DispSyncThread
DispSync::DispSync() : mRefreshSkipCount(0), mThread(new DispSyncThread()) {mThread-> run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); reset(); beginResync(); if (kTraceDetailedInfo) { // If we‘re not getting present fences then the ZeroPhaseTracer // would prevent HW vsync event from ever being turned off. // Even if we‘re just ignoring the fences, the zero-phase tracing is // not needed because any time there is an event registered we will // turn on the HW vsync events. if (!kIgnorePresentFences) { addEventListener(0, new ZeroPhaseTracer()); } } }

  • 调用DispSync的addResyncSample方法,最终会去唤醒DispSyncThread线程
bool DispSync::addResyncSample(nsecs_t timestamp) { Mutex::Autolock lock(mMutex); 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 (kIgnorePresentFences) { // 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 > kErrorThreshold; }

  • 调用updateModelLocked函数
  • 计算是否需要开启硬件VSync,进行同步
void DispSync::updateModelLocked() { if (mNumResyncSamples > = MIN_RESYNC_SAMPLES_FOR_UPDATE) {......mThread-> updateModel(mPeriod, mPhase); } }

  • 成员变量mThread为DispSyncThread类的对象
  • 调用DispSyncThread类pdateModel方法
void updateModel(nsecs_t period, nsecs_t phase) { Mutex::Autolock lock(mMutex); mPeriod = period; mPhase = phase; mCond.signal(); }

  • 该方法主要设置成员变量mPeriod、mPhase
  • 然后在唤醒线程循环
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); ......callbackInvocations = gatherCallbackInvocationsLocked(now); }if (callbackInvocations.size() > 0) { fireCallbackInvocations(callbackInvocations); } }return false; }

  • 通过gatherCallbackInvocationsLocked得到监听者集合
  • 通过fireCallbackInvocations调用监听者回调函数
DispSync的回调函数在哪里注册,我们在看看DispSyncSource的setVSyncEnabled函数
virtual void setVSyncEnabled(bool enable) { Mutex::Autolock lock(mVsyncMutex); 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(mVsyncOnLabel.string(), 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(mVsyncOnLabel.string(), 0); } mEnabled = enable; }

  • DispSyncSource类继承于DispSync::Callback
  • 调用DispSync-> addEventListener注册回调,当DispSyncSource收到DispSync的VSync信号时,会回调整onDispSyncEvent函数
virtual void onDispSyncEvent(nsecs_t when) { sp< VSyncSource::Callback> callback; { Mutex::Autolock lock(mCallbackMutex); callback = mCallback; if (mTraceVsync) { mValue = https://www.songbingjia.com/android/(mValue + 1) % 2; ATRACE_INT(mVsyncEventLabel.string(), mValue); } }if (callback != NULL) { callback-> onVSyncEvent(when); } }

  • 这个函数最终还是调用VSyncSource::Callback的onVSyncEvent函数。
  • VSyncSource::Callback函数的注册是通过调用DispSyncSource的setCallback注册。
【Android SurfaceFlinger服务 ----- VSync信号的分发】DispSyncSource的setCallback函数在哪里调用的呢,要解答这个问题,还是得回到SurfaceFlinger的init函数里,以sfVsyncSrc为例。
void SurfaceFlinger::init() {......// start the EventThread sp< VSyncSource> vsyncSrc = https://www.songbingjia.com/android/new DispSyncSource(& mPrimaryDispSync, vsyncPhaseOffsetNs, true,"app"); mEventThread = new EventThread(vsyncSrc); sp< VSyncSource> sfVsyncSrc = https://www.songbingjia.com/android/new DispSyncSource(& mPrimaryDispSync, sfVsyncPhaseOffsetNs, true,"sf"); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread); ...... }

  • 以sfVsyncSrc为参数创建EventThread对象
  • 在EventThread的线程循环中会去调用enableVSyncLocked函数
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); } } mDebugVsyncEnabled = true; sendVsyncHintOnLocked(); }

  • EventThread继承VSyncSource::Callback接口,实现了onVSyncEvent函数
  • 调用mVSyncSource的setCallback函数设置回调
  • 调用mVSyncSource的setVSyncEnabled函数使能VSync信号的监听
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(); }

  • EventThread收到VSync信号后,发送广播消息,唤醒相关线程
  • 最终EventThread将VSnc信号传递给MessageQueue

    推荐阅读