Andorid Q
一. DispSync DispSyncThread, 软件产生vsync的线程, 也控制硬件VSync信号同步。
接上一篇,SF EventThread在显示屏准备完毕后,会调用enableVSyncLocked,最终是在DispSync的mEventListeners中添加了一个EventListener。 我们先看DispSync线程的创建过程。
二. DispSync初始化 2.1 SurfaceFlinger 1 2 3 4 5 6 7 8 SurfaceFlinger::SurfaceFligner (SurfaceFlinger::SkipInitializationTag) : BnSurfaceComposer (), mTransactionFlags (0 ), ...... mPrimaryDispSync ("PrimaryDispSync" ), mPrimaryHWVsyncEnabled (false ), ...... {}
在SurfaceFlinger初始化的时候创建的。
2.2 DispSync创建 1 2 3 4 5 6 7 8 9 10 11 DispSync::DispSync (const char * name) : mName (name), mRefreshSkipCount (0 ), mThread (new DispSyncThread (name)) {} explicit DispSyncThread (const char * name) : mName(name), mStop(false), mPeriod(0 ), // 注意这里的mPeriod初始化为0 mPhase(0 ), mReferenceTime(0 ), mWakeupLatency(0 ), mFrameNumber(0 ) { }
2.3 SurfaceFlinger::SurfaceFlinger 1 2 3 4 5 6 7 SurfaceFlinger::SurfaceFlinger () : SurfaceFlinger (SkipInitialization) { ALOGI ("SurfaceFlinger is starting" ); ...... mPrimaryDispSync.init (SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset); ...... }
2.4 DispSync.init 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 void DispSync::init (bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) { mIgnorePresentFences = !hasSyncFramework; mPresentTimeOffset = dispSyncPresentTimeOffset; mThread->run ("DispSync" , PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); struct sched_param param = {0 }; param.sched_priority = 2 ; if (sched_setscheduler (mThread->getTid (), SCHED_FIFO, ¶m) != 0 ) { ALOGE ("Couldn't set SCHED_FIFO for DispSyncThread" ); } reset (); beginResync (); if (kTraceDetailedInfo) { if (!mIgnorePresentFences && kEnableZeroPhaseTracer) { mZeroPhaseTracer = std::make_unique <ZeroPhaseTracer>(); addEventListener ("ZeroPhaseTracer" , 0 , mZeroPhaseTracer.get ()); } } }
2.4.1 DispSyncThread.threadLoop 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 virtual bool threadLoop () { status_t err; nsecs_t now = systemTime (SYSTEM_TIME_MONOTONIC); while (true ) { Vector<CallbackInvocation> callbackInvocations; nsecs_t targetTime = 0 ; { Mutex::Autolock lock (mMutex) ; if (kTraceDetailedInfo) { ATRACE_INT64 ("DispSync:Frame" , mFrameNumber); } ALOGV ("[%s] Frame %" PRId64, mName, mFrameNumber); ++mFrameNumber; 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 ; } ...... }
三. enableVysncLocked后续 SF EventThread在显示屏准备完毕后,会调用enableVSyncLocked
3.1 DispSync.addEventListener 1 2 3 4 status_t DispSync::addEventListener(const char* name, nsecs_t phase, Callback* callback) { Mutex::Autolock lock(mMutex); return mThread->addEventListener(name, phase, callback); }
3.2 DispSync.DispSyncThread.addEventListener 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 status_t addEventListener (const char * name, nsecs_t phase, DispSync::Callback* callback) { if (kTraceDetailedInfo) ATRACE_CALL (); Mutex::Autolock lock (mMutex) ; for (size_t i = 0 ; i < mEventListeners.size (); i++) { if (mEventListeners[i].mCallback == callback) { return BAD_VALUE; } } EventListener listener; listener.mName = name; listener.mPhase = phase; listener.mCallback = callback; listener.mLastEventTime = systemTime () - mPeriod / 2 + mPhase - mWakeupLatency; mEventListeners.push (listener); mCond.signal (); return NO_ERROR; }
注意这里还是运行在SurfaceFlinger主线程,在mCond.signal之后,DispSync线程就可以继续执行了。 但是注意看:
1 2 3 4 5 6 7 8 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 ; }
这里的continue意味着如果mPeriod为0,还是会一直等待。
四. setPeriod 这样我们就需要看mPeriod是什么时候被更改的。 在SurfaceFlinger初始化Display后,会调用resyncToHardwareVsync跟硬件vsync进行同步。
1 2 3 4 5 initializeDisplays(); flinger->onInitializeDisplays(); setPowerModeInternal() resyncToHardwareVsync(true); repaintEverything();
4.1 SurfaceFlinger.resyncToHardwareVsync 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void SurfaceFlinger::resyncToHardwareVsync (bool makeAvailable) { Mutex::Autolock _l(mHWVsyncLock); if (makeAvailable) { mHWVsyncAvailable = true ; } else if (!mHWVsyncAvailable) { return ; } const auto & activeConfig = getBE ().mHwc->getActiveConfig (HWC_DISPLAY_PRIMARY); const nsecs_t period = activeConfig->getVsyncPeriod (); mPrimaryDispSync.reset (); mPrimaryDispSync.setPeriod (period); if (!mPrimaryHWVsyncEnabled) { mPrimaryDispSync.beginResync (); mEventControlThread->setVsyncEnabled (true ); mPrimaryHWVsyncEnabled = true ; } }
4.2 DispSync.setPeriod 1 2 3 4 5 6 7 8 void DispSync::setPeriod (nsecs_t period) { Mutex::Autolock lock (mMutex) ; mPeriod = period; mPhase = 0 ; mReferenceTime = 0 ; }
mPeriod表示具体的硬件产生vsync的时间间隔。这样,之后的DispSync线程中的threadLoop就可以继续执行了。
五. 硬件Vsync的开关控制 接上面 4.1,当设置DispSync的mPeriod之后,如果硬件Vsync开关是开启状态,则会通过EventControlThread打开HW Vsync 我们先看看EventControlThread线程的启动,其启动在SurfaceFlinger的初始化,EventThread启动之后,显示屏初始化之前。
5.1 EventControlThread的启动 1 2 3 4 5 6 7 8 9 10 11 12 13 void SurfaceFlinger::init () { ...... mEventControlThread = std::make_unique <impl::EventControlThread>( [this ](bool enabled) { setVsyncEnabled (HWC_DISPLAY_PRIMARY, enabled); }); ...... } void SurfaceFlinger::setVsyncEnabled (int disp, int enabled) { ATRACE_CALL (); Mutex::Autolock lock (mStateLock) ; getHwComposer ().setVsyncEnabled (disp, enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable); }
这里初始化时传入了函数 setVsyncEnabled。
注意EventControlThread中线程的初始化是在成员变量中:
1 2 std::thread mThread{&EventControlThread::threadMain, this };
所以先调用threadMain,后调用构造函数。
5.1.1 EventControlThread.threadMain 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void EventControlThread::threadMain () NO_THREAD_SAFETY_ANALYSIS { auto keepRunning = true ; auto currentVsyncEnabled = false ; while (keepRunning) { mSetVSyncEnabled (currentVsyncEnabled); std::unique_lock<std::mutex> lock (mMutex) ; mCondition.wait (lock, [this , currentVsyncEnabled, keepRunning]() NO_THREAD_SAFETY_ANALYSIS { return currentVsyncEnabled != mVsyncEnabled || keepRunning != mKeepRunning; }); currentVsyncEnabled = mVsyncEnabled; keepRunning = mKeepRunning; } }
5.1.2 EventControlThread初始化 1 2 3 4 5 6 7 8 EventControlThread::EventControlThread (EventControlThread::SetVSyncEnabledFunction function) : mSetVSyncEnabled (function) { pthread_setname_np (mThread.native_handle (), "EventControlThread" ); pid_t tid = pthread_gettid_np (mThread.native_handle ()); setpriority (PRIO_PROCESS, tid, ANDROID_PRIORITY_URGENT_DISPLAY); set_sched_policy (tid, SP_FOREGROUND); }
构造函数里面设置了线程名和优先级
5.2 EventControlThread.setVsyncEnabled 1 2 3 4 5 void EventControlThread::setVsyncEnabled (bool enabled) { std::lock_guard<std::mutex> lock (mMutex) ; mVsyncEnabled = enabled; mCondition.notify_all (); }
mVsyncEnabled设置为true, 表明开启硬件Vsync. mCondition.notify_all() 则通知EventControlThread线程继续执行,回到5.1.1的循环内。 mSetVSyncEnabled是传入的函数SurfaceFlinger.setVsyncEnabled.
5.3 SurfaceFlinger.setVsyncEnabled 1 2 3 4 5 6 7 8 9 void SurfaceFlinger::setVsyncEnabled (int disp, int enabled) { ATRACE_CALL (); Mutex::Autolock lock (mStateLock) ; getHwComposer ().setVsyncEnabled (disp, enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable); } HWComposer& getHwComposer () const { return *getBE ().mHwc; }SurfaceFlingerBE& getBE () { return mBE; }
这里的disp = HWC_DISPLAY_PRIMARY
5.4 HWComposer.setVsyncEnabled 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 void HWComposer::setVsyncEnabled (DisplayId displayId, HWC2::Vsync enabled) { RETURN_IF_INVALID_DISPLAY (displayId); auto & displayData = mDisplayData[displayId]; if (displayData.isVirtual) { LOG_DISPLAY_ERROR (displayId, "Invalid operation on virtual display" ); return ; } std::lock_guard lock (displayData.vsyncEnabledLock) ; if (enabled == displayData.vsyncEnabled) { return ; } ATRACE_CALL (); auto error = displayData.hwcDisplay->setVsyncEnabled (enabled); RETURN_IF_HWC_ERROR (error, displayId); displayData.vsyncEnabled = enabled; const auto tag = "HW_VSYNC_ON_" + to_string (displayId); ATRACE_INT (tag.c_str (), enabled == HWC2::Vsync::Enable ? 1 : 0 ); }
六. 硬件Vsync信号更新 经过HWComposer使能硬件Vsync信号后,只要有硬件Vsync信号产生,就可回调 hook_vsync函数。 hook_vsync函数在HWComposer的初始化的时候被注册的。
6.1 HWC初始化 1 2 3 4 5 6 7 8 9 void SurfaceFlinger::init() { ...... // 获取硬件HWC getBE().mHwc.reset( new HWComposer(std::make_unique<Hwc2::impl::Composer>(getBE().mHwcServiceName))); // 注册回调 getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId); ...... }
这里这里先创建的是 Hwc2::impl::Composer,然后创建HWComposer
6.1.1 ComposerHal.cpp:Composer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 Composer::Composer (const std::string& serviceName) : mWriter (kWriterInitialSize), mIsUsingVrComposer (serviceName == std::string ("vr" )) { mComposer = V2_1::IComposer::getService (serviceName); if (mComposer == nullptr ) { LOG_ALWAYS_FATAL ("failed to get hwcomposer service" ); } mComposer->createClient ( [&](const auto & tmpError, const auto & tmpClient) { if (tmpError == Error::NONE) { mClient = tmpClient; } }); if (mClient == nullptr ) { LOG_ALWAYS_FATAL ("failed to create composer client" ); } sp<IComposer> composer_2_2 = IComposer::castFrom (mComposer); if (composer_2_2 != nullptr ) { mClient_2_2 = IComposerClient::castFrom (mClient); LOG_ALWAYS_FATAL_IF (mClient_2_2 == nullptr , "IComposer 2.2 did not return IComposerClient 2.2" ); } if (mIsUsingVrComposer) { sp<IVrComposerClient> vrClient = IVrComposerClient::castFrom (mClient); if (vrClient == nullptr ) { LOG_ALWAYS_FATAL ("failed to create vr composer client" ); } } }
获取composer服务。
6.1.2 HWComposer创建 1 2 HWComposer::HWComposer (std::unique_ptr<android::Hwc2::Composer> composer) : mHwcDevice (std::make_unique <HWC2::Device>(std::move (composer))) {}
6.2 注册回调HWComposer.registerCallback 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 void HWComposer::registerCallback (HWC2::ComposerCallback* callback, int32_t sequenceId) { mHwcDevice->registerCallback (callback, sequenceId); } void Device::registerCallback (ComposerCallback* callback, int32_t sequenceId) { if (mRegisteredCallback) { ALOGW ("Callback already registered. Ignored extra registration " "attempt." ); return ; } mRegisteredCallback = true ; sp<ComposerCallbackBridge> callbackBridge ( new ComposerCallbackBridge(callback, sequenceId)) ; mComposer->registerCallback (callbackBridge); } void Composer::registerCallback (const sp<IComposerCallback>& callback) { auto ret = mClient->registerCallback (callback); if (!ret.isOk ()) { ALOGE ("failed to register IComposerCallback" ); } }
ComposerCallbackBridge类就是实现onHotplug, onVsync等回调。 当HWC硬件产生vsync信号时,就会回调onVsync方法。
6.3 Vsync信号更新 6.3.1 ComposerCallbackBridge.onVsync 1 2 3 4 5 Return<void > onVsync (Hwc2::Display display, int64_t timestamp) override { mCallback->onVsyncReceived (mSequenceId, display, timestamp); return Void (); }
这里的mCallback就是SurfaceFlinger[6.1].
6.3.2 SurfaceFlinger.onVsyncReceived 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void SurfaceFlinger::onVsyncReceived (int32_t sequenceId, hwc2_display_t displayId, int64_t timestamp) { Mutex::Autolock lock (mStateLock) ; if (sequenceId != getBE ().mComposerSequenceId) { return ; } int32_t type; if (!getBE ().mHwc->onVsync (displayId, timestamp, &type)) { return ; } bool needsHwVsync = false ; { Mutex::Autolock _l(mHWVsyncLock); if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) { needsHwVsync = mPrimaryDispSync.addResyncSample (timestamp); } } if (needsHwVsync) { enableHardwareVsync (); } else { disableHardwareVsync (false ); } }
6.3.3 DispSync.addResyncSample 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 bool DispSync::addResyncSample (nsecs_t timestamp) { Mutex::Autolock lock (mMutex) ; ALOGV ("[%s] addResyncSample(%" PRId64 ")" , mName, ns2us (timestamp)); size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES; mResyncSamples[idx] = timestamp; if (mNumResyncSamples == 0 ) { mPhase = 0 ; mReferenceTime = timestamp; ALOGV ("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, " "mReferenceTime = %" PRId64, mName, ns2us (mPeriod), ns2us (mReferenceTime)); mThread->updateModel (mPeriod, mPhase, mReferenceTime); } if (mNumResyncSamples < MAX_RESYNC_SAMPLES) { mNumResyncSamples++; } else { mFirstResyncSample = (mFirstResyncSample + 1 ) % MAX_RESYNC_SAMPLES; } updateModelLocked (); if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) { resetErrorLocked (); } if (mIgnorePresentFences) { return mThread->hasAnyEventListeners (); } bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2 ); ALOGV ("[%s] addResyncSample returning %s" , mName, modelLocked ? "locked" : "unlocked" ); return !modelLocked; }
这里是收到硬件Vsync信号, 在SurfaceFlinger主线程执行,在经过误差更正后,通知DispSync线程处理分发事件。
6.3.4 DispSync.updateModelLocked 这一步是计算模型参数如偏移、硬件Vsync更新间隔等。在分析前,我们先了解下几个重要参数的含义:
参数名
默认值
含义
mNumResyncSamples
-
当前保存的硬件Vsyc信号数量,最大值为32
MIN_RESYNC_SAMPLES_FOR_UPDATE
6
更新模型参数的最小硬件Vsync数量
mPeriod
-
硬件刷新率,根据保存的Vsync去掉最大和最小求得的平均值
mPhase
-
偏移时间,仅作为针对mPeriod的一个偏移
mReferenceTime
第一个硬件Vsync事件
每次计算sw vsync模型时的基准时间,以减少误差
mRefreshSkipCount
0
多少个vsync才进行刷新,可以通过这个人为的降低显示设备刷新率(软件刷新率)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 void DispSync::updateModelLocked () { ALOGV ("[%s] updateModelLocked %zu" , mName, mNumResyncSamples); if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) { ALOGV ("[%s] Computing..." , mName); nsecs_t durationSum = 0 ; nsecs_t minDuration = INT64_MAX; nsecs_t maxDuration = 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; nsecs_t duration = mResyncSamples[idx] - mResyncSamples[prev]; durationSum += duration; minDuration = min (minDuration, duration); maxDuration = max (maxDuration, duration); } durationSum -= minDuration + maxDuration; mPeriod = durationSum / (mNumResyncSamples - 3 ); ALOGV ("[%s] mPeriod = %" PRId64, mName, ns2us (mPeriod)); double sampleAvgX = 0 ; double sampleAvgY = 0 ; double scale = 2.0 * M_PI / double (mPeriod); for (size_t i = 1 ; i < mNumResyncSamples; i++) { size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES; nsecs_t sample = mResyncSamples[idx] - mReferenceTime; double samplePhase = double (sample % mPeriod) * scale; sampleAvgX += cos (samplePhase); sampleAvgY += sin (samplePhase); } sampleAvgX /= double (mNumResyncSamples - 1 ); sampleAvgY /= double (mNumResyncSamples - 1 ); mPhase = nsecs_t (atan2 (sampleAvgY, sampleAvgX) / scale); ALOGV ("[%s] mPhase = %" PRId64, mName, ns2us (mPhase)); if (mPhase < -(mPeriod / 2 )) { mPhase += mPeriod; ALOGV ("[%s] Adjusting mPhase -> %" PRId64, mName, ns2us (mPhase)); } if (kTraceDetailedInfo) { ATRACE_INT64 ("DispSync:Period" , mPeriod); ATRACE_INT64 ("DispSync:Phase" , mPhase + mPeriod / 2 ); } mPeriod += mPeriod * mRefreshSkipCount; mThread->updateModel (mPeriod, mPhase, mReferenceTime); mModelUpdated = true ; } }
这里算偏移还用上了反三角函数。mPeriod的含义就是圆周长,最终算出来的 mPhase 就是弧BC的长度。 也就是基于mPeriod的偏移值,如下图:
这个偏移值有什么用处呢?
6.3.5 DispSync.DispSyncThread.updateModel 1 2 3 4 5 6 7 8 9 10 11 12 void updateModel (nsecs_t period, nsecs_t phase, nsecs_t referenceTime) { if (kTraceDetailedInfo) ATRACE_CALL (); Mutex::Autolock lock (mMutex) ; mPeriod = period; mPhase = phase; mReferenceTime = referenceTime; ALOGV ("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64 " mReferenceTime = %" PRId64, mName, ns2us (mPeriod), ns2us (mPhase), ns2us (mReferenceTime)); mCond.signal (); }
更新mPeriod和时间戳。 mCond.signal 后转DispSyncThread线程[2.4.1]DispSyncThread.threadLoop继续执行
七. SW Vsync更新 硬件Vsync信号经过DispSync的简单加工,会将相应的值更新,然后唤醒DispSyncThread线程
7.1 DispSync.DispSyncThread.threadLoop 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 virtual bool threadLoop () { status_t err; nsecs_t now = systemTime (SYSTEM_TIME_MONOTONIC); while (true ) { Vector<CallbackInvocation> callbackInvocations; nsecs_t targetTime = 0 ; { Mutex::Autolock lock (mMutex) ; if (kTraceDetailedInfo) { ATRACE_INT64 ("DispSync:Frame" , mFrameNumber); } ALOGV ("[%s] Frame %" PRId64, mName, mFrameNumber); ++mFrameNumber; 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 ; } targetTime = computeNextEventTimeLocked (now); bool isWakeup = false ; if (now < targetTime) { if (kTraceDetailedInfo) ATRACE_NAME ("DispSync waiting" ); if (targetTime == INT64_MAX) { ALOGV ("[%s] Waiting forever" , mName); err = mCond.wait (mMutex); } else { ALOGV ("[%s] Waiting until %" PRId64, mName, ns2us (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); static const nsecs_t kMaxWakeupLatency = us2ns (1500 ); if (isWakeup) { mWakeupLatency = ((mWakeupLatency * 63 ) + (now - targetTime)) / 64 ; mWakeupLatency = min (mWakeupLatency, kMaxWakeupLatency); if (kTraceDetailedInfo) { ATRACE_INT64 ("DispSync:WakeupLat" , now - targetTime); ATRACE_INT64 ("DispSync:AvgWakeupLat" , mWakeupLatency); } } callbackInvocations = gatherCallbackInvocationsLocked (now); } if (callbackInvocations.size () > 0 ) { fireCallbackInvocations (callbackInvocations); } } return false ; }
7.2 DispSync.DispSyncThread.computeNextEventTimeLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 nsecs_t computeNextEventTimeLocked (nsecs_t now) { if (kTraceDetailedInfo) ATRACE_CALL (); ALOGV ("[%s] computeNextEventTimeLocked" , mName); nsecs_t nextEventTime = INT64_MAX; for (size_t i = 0 ; i < mEventListeners.size (); i++) { nsecs_t t = computeListenerNextEventTimeLocked (mEventListeners[i], now); if (t < nextEventTime) { nextEventTime = t; } } ALOGV ("[%s] nextEventTime = %" PRId64, mName, ns2us (nextEventTime)); return nextEventTime; }
这里的EventListeners里面只有两个,一个是SF EventThread,另一个就是App EventThread.
7.2.1 DispSync.DispSyncThread.computeListenerNextEventTimeLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 nsecs_t computeListenerNextEventTimeLocked (const EventListener& listener, nsecs_t baseTime) { nsecs_t lastEventTime = listener.mLastEventTime + mWakeupLatency; if (baseTime < lastEventTime) { baseTime = lastEventTime; } baseTime -= mReferenceTime; nsecs_t phase = mPhase + listener.mPhase; baseTime -= phase; if (baseTime < 0 ) { baseTime = -mPeriod; } nsecs_t numPeriods = baseTime / mPeriod; nsecs_t t = (numPeriods + 1 ) * mPeriod + phase; t += mReferenceTime; ALOGV ("[%s] Absolute t = %" PRId64, mName, ns2us (t)); if (t - listener.mLastEventTime < (3 * mPeriod / 5 )) { t += mPeriod; } t -= mWakeupLatency; return t; }
如下图:
看到这里就有一个疑问,sw vsync信号是在DispSyncThread收到第一个硬件Vsync更新sw model后就可以不依赖 硬件Vsync信号了,后续可以自己产生。那为什么google没有在这里disable硬件Vsync呢,因为sw vsync还是有误差 并不能与硬件Vsync完全保持一致,所以需要updateModelLocked持续消减误差。 重新梳理一下完整流程:
SurfaceFlinger主线程收到硬件Vsync
DispSync.updateModelLocked及时更新sw model,并通知DispSyncThread线程
DispSyncThread线程更新mPeriod,mPhase等参数通过computeNextEventTimeLocked计算新的targetTime
继续等待直到新的targetTime,通知SF EventThread或者AppEventThread有sw vsync信号
我们知道SF EventThread和App EventThread是有间隔的,并不同步,这里是如何实现的呢? 注意我们计算出来的targetTime是sf和app中最近的一次,那么继续看往下看。
7.3 DispSync.DispSyncThread.gatherCallbackInvocationsLocked now是当前应该被触发的sw vsync时间点,可能是sf vsync也可能是app vsync。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Vector<CallbackInvocation> gatherCallbackInvocationsLocked (nsecs_t now) { Vector<CallbackInvocation> callbackInvocations; nsecs_t onePeriodAgo = now - mPeriod; for (size_t i = 0 ; i < mEventListeners.size (); i++) { nsecs_t t = computeListenerNextEventTimeLocked (mEventListeners[i], onePeriodAgo); if (t < now) { CallbackInvocation ci; ci.mCallback = mEventListeners[i].mCallback; ci.mEventTime = t; callbackInvocations.push (ci); mEventListeners.editItemAt (i).mLastEventTime = t; } } return callbackInvocations; }
看完这个方法,其实不难理解,DispSyncThread中的targetTime是变化的值,有可能是app EventThread的下一次sw vsync时间,也可能是sf的。如下图:
到这里,sw vsync的流程基本梳理完毕了。
接下来继续看EventThread.
参考资料
Android SurfaceFlinger SW Vsync模型
DispSync
DispSync详解