Android 12(S) 影像顯示系統 – SurfaceFlinger之VSync-上篇(十六)

必讀:

Android 12(S) 影像顯示系統 – 開篇


 

一、前言


為了提高Android系統的UI交互速度和操作的流暢度,在Android 4.1中,引入了Project Butter,即「黃油計劃」。就像該計劃的名字那樣,Google期望通過這一新的機制可以讓Android系統擺脫UI交互時給用戶帶來的滯後感,從而像黃油一樣順滑。

當然優化是無止境的,Project Butter只是邁出了重要的第一步,後續的Android版本中陸續也有引入一些其它的優化機制,促進UI渲染性能的不斷提升。

Project Butter對Android Display系統進行了重構,引入了三個核心元素:VSyncTriple BufferChoreographer。從這篇文章開始,我們就來看一看VSync的實現機制。

關於螢幕刷新機制,有一張很經典的圖片:

整個顯示過程就是:

  • CPU計算螢幕需要的數據,然後交給GPU。
  • GPU對影像進行處理繪製,然後存到快取區。
  • display再從這個快取區讀取數據,顯示出來。

如果螢幕的刷新率是60Hz,每一幀都是重複這個工作,也就是1秒中需要60次這樣循環操作,每次操作需要的時間就約等於16.6ms。也就是我們常說的Android系統中,會每隔16.6ms刷新一次螢幕。

可以看到,16.6ms一到,系統就發送了VSync訊號,然後螢幕會從快取區獲取了新的一幀影像並顯示出來,與此同時,CPU也開始了下一幀數據的計算,然後計算好交給GPU,最後放到快取區,等待下一次VSync訊號。

 

在閱讀這篇文章前,推薦閱讀一篇我轉載的文章:聊聊Android螢幕刷新機制 – Vsync / Double Buffer / Triple Buffer / 掉幀 / 撕裂

 

二、VSYNC訊號的產生


 

2.1 VSync訊號機制的邏輯是從哪裡開始初始化的呢?

在前面的文章 Android 12(S) 影像顯示系統 – SurfaceFlinger的啟動和消息隊列處理機制(四)中我們在講解SurfaceFlinger::init方法時,init會去初始化HWComposer並註冊回調函數,如下摘錄的程式碼:

[/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::init() {
    // 創建HWComposer對象並傳入一個name屬性,再通過mCompositionEngine->setHwComposer設置對象屬性。
    mCompositionEngine->setTimeStats(mTimeStats);
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    mCompositionEngine->getHwComposer().setCallback(this); // 這裡的this就是SurfaceFlinger對象本身,因為它實現了HWC2::ComposerCallback回調介面
}

HWC2::ComposerCallback中定義了 VSYNC訊號、插拔顯示器等的回調事件方法,如下:

[/frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h]
struct ComposerCallback {
    virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0; // 熱插拔事件
    virtual void onComposerHalRefresh(hal::HWDisplayId) = 0; // refresh 刷新事件
    virtual void onComposerHalVsync(hal::HWDisplayId, int64_t timestamp, // VSYNC訊號事件
                                    std::optional<hal::VsyncPeriodNanos>) = 0;
    ...
};

根據HWC2::ComposerCallback的設計邏輯,SurfaceFlinger::init方法中設置完HWC的回調後,會立即收到一個Hotplug事件,並在SurfaceFlinger::onComposerHalHotplug中去處理,因此流程就走到了:

[/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::onComposerHalHotplug(hal::HWDisplayId hwcDisplayId,
                                          hal::Connection connection) {
    ...
    if (std::this_thread::get_id() == mMainThreadId) {
        // Process all pending hot plug events immediately if we are on the main thread.
        processDisplayHotplugEventsLocked(); // 主執行緒中去處理 hot plug evnets
    }
}

再看processDisplayHotplugEventsLocked的程式碼:

[/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
        if (event.connection == hal::Connection::CONNECTED) {
                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
                    initScheduler(state); // 初始化Scheduler
                }
                .....
}

上述程式碼我們只關心和VSync信後相關的邏輯,那就是調用了initShceduler

[/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
    if (mScheduler) { // 判斷mScheduler是否為空,避免重複初始化
        // In practice it's not allowed to hotplug in/out the primary display once it's been
        // connected during startup, but some tests do it, so just warn and return.
        ALOGW("Can't re-init scheduler");
        return;
    }
    const auto displayId = displayState.physical->id;
    scheduler::RefreshRateConfigs::Config config =
            {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
             .frameRateMultipleThreshold =
                     base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
    // 刷新率的配置資訊,裡面包含了當前的螢幕刷頻率。刷新周期等資訊
    mRefreshRateConfigs =
            std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
                                                            displayState.physical->activeMode
                                                                    ->getId(),
                                                            config);
    // currRefreshRate是一個Fps Object,其中存儲了刷新率fps和刷新周期period
    const auto currRefreshRate = displayState.physical->activeMode->getFps();
    mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
                                                                      hal::PowerMode::OFF);
    // mVsyncConfiguration 是一個 VsyncConfiguration object
    // VsyncConfiguration 類中封裝了不同刷新率下的VSYNC配置資訊。app phase 就是vsyncSrc偏移量,sf phase 是sfVsyncSrc偏移量,
    mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);
    // VsyncModulator object,VSYNC調製器,根據事務調度和刷新率的變化調整VSYNC偏移量。 
    mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());

    // 創建Scheduler object
    mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
    const auto configs = mVsyncConfiguration->getCurrentConfigs();
    const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
    // 創建一個Connection named "app"
    mAppConnectionHandle =
            mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/configs.late.appWorkDuration,
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         impl::EventThread::InterceptVSyncsCallback());
    // 創建一個Connection named "appSf" 
    mSfConnectionHandle =
            mScheduler->createConnection("appSf", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         [this](nsecs_t timestamp) {
                                             mInterceptor->saveVSyncEvent(timestamp);
                                         });
    //initVsync主要作用是綁定一個回調函數 MessageQueue::vsyncCallback 到VSyncDispatch上,回調名字"sf"
    mEventQueue->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
                           configs.late.sfWorkDuration);

    mRegionSamplingThread =
            new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables());
    mFpsReporter = new FpsReporter(*mFrameTimeline, *this);

    mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId,
                                            displayState.physical->activeMode->getId(),
                                            vsyncPeriod);
    static auto ignorePresentFences =
            base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
    mScheduler->setIgnorePresentFences(
            ignorePresentFences ||
            getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE));
}

我們可以dumpsys SurfaceFlinger看一看,VSyncDispatch上都綁定了哪些Callbacks,如下資訊:有三個「sf」,"appSf", "app"是不是和我們initShceduler

程式碼中的邏輯冥冥之中有點呼應了…

VSyncDispatch:
	Timer:
		DebugState: Waiting
	mTimerSlack: 0.50ms mMinVsyncDistance: 3.00ms
	mIntendedWakeupTime: 9223369916416.00ms from now
	mLastTimerCallback: 4215.62ms ago mLastTimerSchedule: 4215.54ms ago
	Callbacks:
		sf:  
			workDuration: 15.67ms readyDuration: 0.00ms earliestVsync: -11799.97ms relative to now
			mLastDispatchTime: 4200.02ms ago
		appSf:
			workDuration: 16.67ms readyDuration: 15.67ms earliestVsync: -2153016.50ms relative to now
			mLastDispatchTime: 2153016.50ms ago
		app:  
			workDuration: 16.67ms readyDuration: 15.67ms earliestVsync: -4183.37ms relative to now
			mLastDispatchTime: 4183.37ms ago

對前面的流程小結一下,大概如下:

接下來我們深入initShceduler細節,看看每一步驟都具體做了什麼工作呢?

 

2.2 創建Scheduler對象都做了啥子?

開啟創建之旅….

[/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
    ...
    // start the EventThread
    mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this); //在DefaultFactory中去執行創建操作
    ...
}

DefaultFactory中也很簡單,SurfaceFlinger有實現ISchedulerCallback回調方法,參數callback指向一個SurfaceFlinger對象,參數configs是刷新率的資訊

[ /frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp]
std::unique_ptr<Scheduler> DefaultFactory::createScheduler(
        const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) {
    return std::make_unique<Scheduler>(configs, callback); // 創建Scheduler對象,callback指向一個SurfaceFlinger Object
}

進到Scheduler的構造函數,三個構造函數依次調用,初始化必要成員變數。

[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
      : Scheduler(configs, callback,
                  {.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
                   .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
}

Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
                     Options options)
      : Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,//createVsyncSchedule是主要的邏輯
                  createLayerHistory(configs), options) {
    ...
}

Scheduler::Scheduler(VsyncSchedule schedule, const scheduler::RefreshRateConfigs& configs,
                     ISchedulerCallback& schedulerCallback,
                     std::unique_ptr<LayerHistory> layerHistory, Options options)
      : mOptions(options),
        mVsyncSchedule(std::move(schedule)),
        mLayerHistory(std::move(layerHistory)),
        mSchedulerCallback(schedulerCallback),
        mRefreshRateConfigs(configs),
        mPredictedVsyncTracer(
                base::GetBoolProperty("debug.sf.show_predicted_vsync", false)
                        ? std::make_unique<PredictedVsyncTracer>(*mVsyncSchedule.dispatch)
                        : nullptr) {
    mSchedulerCallback.setVsyncEnabled(false);// 注意這裡,設置了 VSync Enable False,關閉了硬體VSync
}

Scheduler構造函數中,最重要的一個步驟就是去調用了createVsyncSchedule方法,這是一個核心方法,在其中創建和初始化了和VSync訊號產生、分發相關的類對象和運行邏輯。

本文作者@二的次方  2022-04-18 發佈於部落格園

[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(bool supportKernelTimer) {
    auto clock = std::make_unique<scheduler::SystemClock>();
    auto tracker = createVSyncTracker();  // 創建VSyncTracker對象
    auto dispatch = createVSyncDispatch(*tracker); // 創建VSyncDispatch對象

    // TODO(b/144707443): Tune constants.
    constexpr size_t pendingFenceLimit = 20;
    auto controller =                   // 創建VSyncReactor對象
            std::make_unique<scheduler::VSyncReactor>(std::move(clock), *tracker, pendingFenceLimit,
                                                      supportKernelTimer); 
    return {std::move(controller), std::move(tracker), std::move(dispatch)}; // 把tracker,dispatch,controller封裝在一個VsyncSchedule strcut中
}

createVsyncSchedule方法最終返回了一個VsyncSchedule結構體對象。VsyncSchedule是一個結構體類型,含有三個成員變數:controller、tracker、dispatch,這三個成員在 VSync機制中分別發揮不同作用,等到下面再分析。

[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.h]
struct VsyncSchedule {
    std::unique_ptr<scheduler::VsyncController> controller;
    std::unique_ptr<scheduler::VSyncTracker> tracker;
    std::unique_ptr<scheduler::VSyncDispatch> dispatch;
};

 

2.2.1 先看創建VSyncTracker做了啥?

[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
std::unique_ptr<scheduler::VSyncTracker> createVSyncTracker() {
    // TODO(b/144707443): Tune constants.
    constexpr int kDefaultRate = 60;
    constexpr auto initialPeriod = std::chrono::duration<nsecs_t, std::ratio<1, kDefaultRate>>(1);
    constexpr nsecs_t idealPeriod =
            std::chrono::duration_cast<std::chrono::nanoseconds>(initialPeriod).count();
    constexpr size_t vsyncTimestampHistorySize = 20;
    constexpr size_t minimumSamplesForPrediction = 6; // 為了預測、模擬VSync最少需要取樣的個數
    constexpr uint32_t discardOutlierPercent = 20;
    return std::make_unique<scheduler::VSyncPredictor>(idealPeriod, vsyncTimestampHistorySize,
                                                       minimumSamplesForPrediction,
                                                       discardOutlierPercent);
}

實際創建的是一個實現類VsyncPredictor對象,VSyncTracker是一個基於歷史Vsync時間數據提供未來Vsync訊號時間估計的介面,VsyncPredictor實現了VSyncTracker中的方法。

[/frameworks/native/services/surfaceflinger/Scheduler/VSyncTracker.h]
class VSyncTracker { //虛基類,介面類,VSyncTracker是一個基於歷史Vsync時間數據提供未來Vsync訊號時間估計的介面。

[ /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h]
class VSyncPredictor : public VSyncTracker { //實現VSyncTracker的方法

其中有2個方法,添加 取樣的vsync 時間戳,一般來自HWVsync,基於這些Vsync時間數據來訓練一個模擬的VSync模型,從而達到預測未來VSync時間的目的。

    /*
     * Adds a known timestamp from a vsync timing source (HWVsync signal, present fence)
     * to the model.
     */
    virtual bool addVsyncTimestamp(nsecs_t timestamp) = 0;

    /*
     * Access the next anticipated vsync time such that the anticipated time >= timePoint.
     * This will always give the best accurate at the time of calling; multiple
     * calls with the same timePoint might give differing values if the internal model
     * is updated.
     */
    virtual nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const = 0;

至於如何計算、預測的,本文不做講解。


我的理解是:VSync訊號是由HWC硬體模組根據螢幕刷新率產生。VSyncTrackerVsyncPredictor根據HWC產生的硬體VSync訊號,訓練了一個模擬的VSync事件源,可以預測vsync事件的時間點。


 

2.2.2 創建VSyncDispatch做了啥子呢?

先瞅瞅程式碼吧,很簡單創建了一個VSyncDispatchTimerQueue對象,這又是個什麼鬼?

[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
std::unique_ptr<scheduler::VSyncDispatch> createVSyncDispatch(scheduler::VSyncTracker& tracker) {
    // TODO(b/144707443): Tune constants.
    constexpr std::chrono::nanoseconds vsyncMoveThreshold = 3ms;
    constexpr std::chrono::nanoseconds timerSlack = 500us;
    return std::make_unique<
            scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), tracker,
                                                timerSlack.count(), vsyncMoveThreshold.count());
}

先看看定義吧

[/frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatch.h]
class VSyncDispatch { // 用於分發和系統VSync事件相關的回調事件

[/frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp]
// VSyncDispatchTimerQueue是一個類,它將使用單個計時器隊列按照VSyncDispatch介面調度回調。
class VSyncDispatchTimerQueue : public VSyncDispatch { 

根據程式碼注釋和基本的邏輯,我大概理解的是:

VSyncDispatchTimerQueue(VSyncDispatch)負責分發VSync回調事件,需要接收VSync事件的模組可以通過registerCallback向其中註冊回調函數,所有的回調都保存在了CallbackMap mCallbacks,當到了VSync發生的時間就會遍歷註冊的回調,把VSync事件分發出去。

 

2.2.3 還創建了一個VsyncController對象

    auto controller =
            std::make_unique<scheduler::VSyncReactor>(std::move(clock), *tracker, pendingFenceLimit,
                                                      supportKernelTimer);

VSyncReactor繼承了VsyncController並實現其中的方法,VSyncReactor中含有一個VSyncTracker成員。看它的程式碼,VSyncReactor對外提供addPresentFenceaddHwVsyncTimestamp方法,把HWVsync signal, present fence的vsync timing source傳遞給VSyncTracker用於VSync model的訓練。

 

這一塊的邏輯,涉及到各種類,看起來很是紛繁複雜,我自己都繞來繞去看暈了,對於大多數人來說,這塊的邏輯是不會去修改的,那我也就簡單看看吧。

本文中很多流程也是自己猜測的,大概也不正確吧

 

簡單總結下上面的各種類的作用:

介面類 實現類 作用
VSyncTracker VSyncPredictor 根據取樣的硬體VSync,建立一個模擬的VSync模型,基於歷史Vsync時間數據來預測未來Vsync訊號發生的時間點
VSyncDispatch VSyncDispatchTimerQueue 分發VSync回調事件
VsyncController VSyncReactor 配合VSyncTracker進行硬體VSync的取樣

本文作者@二的次方  2022-04-18 發佈於部落格園

看到這裡有個疑問:VSync事件具體是從哪裡分發出去的呢?

當某一些邏輯需要使用VSync事件驅動時,一般會去調用:

VSyncDispatchTimerQueue::schedule ==> VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor==> VSyncDispatchTimerQueue::setTimer

比如下面就是invalidate的調用棧資訊

11-13 01:15:27.751   225   624 E SurfaceFlinger: stackdump:#00 pc 000c405f  /system/bin/surfaceflinger (android::scheduler::VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(long long, std::__1::__hash_map_iterator<std::__1::__hash_iterator<std::__1::__hash_node<std::__1::__hash_value_type<android::StrongTyping<unsigned int, android::scheduler::CallbackTokenTag, android::Compare, android::Hash>, std::__1::shared_ptr<android::scheduler::VSyncDispatchTimerQueueEntry> >, void*>*> > const&)+686)
11-13 01:15:27.751   225   624 E SurfaceFlinger: stackdump:#01 pc 000c4a99  /system/bin/surfaceflinger (android::scheduler::VSyncDispatchTimerQueue::schedule(android::StrongTyping<unsigned int, android::scheduler::CallbackTokenTag, android::Compare, android::Hash>, android::scheduler::VSyncDispatch::ScheduleTiming)+728)
11-13 01:15:27.751   225   624 E SurfaceFlinger: stackdump:#02 pc 000c5057  /system/bin/surfaceflinger (android::scheduler::VSyncCallbackRegistration::schedule(android::scheduler::VSyncDispatch::ScheduleTiming)+40)
11-13 01:15:27.751   225   624 E SurfaceFlinger: stackdump:#03 pc 000b9beb  /system/bin/surfaceflinger (android::impl::MessageQueue::invalidate()+90)

setTimer中會去設置一個定時器,定時時間到來時,就會回調 VSyncDispatchTimerQueue::timerCallback,在這個函數中遍歷所有的callbacks,進行VSync事件分發。

 

那還有一個問題:都有哪些模組或邏輯使用VSyncDispatchTimerQueue::registerCallback註冊了回調來監聽VSync事件呢?

 

我們再回到SurfaceFlinger中的initScheduler方法,繼續之前的分析

 

2.3 createConnection是何方神聖?

mAppConnectionHandle =
            mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/configs.late.appWorkDuration,
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         impl::EventThread::InterceptVSyncsCallback());

先看看程式碼吧

Scheduler::ConnectionHandle Scheduler::createConnection(
        const char* connectionName, frametimeline::TokenManager* tokenManager,
        std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration); //創建了一個DispSyncSource對象
    auto throttleVsync = makeThrottleVsyncCallback();
    auto getVsyncPeriod = makeGetVsyncPeriodFunction();
    auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager, // 創建了一個EventThread對象
                                                           std::move(interceptCallback),
                                                           std::move(throttleVsync),
                                                           std::move(getVsyncPeriod));
    return createConnection(std::move(eventThread));
}

上面的方法中幹了兩件大事:創建DispSyncSource對象和EventThread對象

 

創建DispSyncSource對象做了啥?

std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
        const char* name, std::chrono::nanoseconds workDuration,
        std::chrono::nanoseconds readyDuration, bool traceVsync) {
    // mVsyncSchedule.dispatch 就是在Scheduler創建時,創建的VSyncDispatchTimerQueue對象
    return std::make_unique<scheduler::DispSyncSource>(*mVsyncSchedule.dispatch, workDuration,
                                                       readyDuration, traceVsync, name);
}

再看DispSyncSource的構造函數:

DispSyncSource::DispSyncSource(scheduler::VSyncDispatch& vSyncDispatch,
                               std::chrono::nanoseconds workDuration,
                               std::chrono::nanoseconds readyDuration, bool traceVsync,
                               const char* name)
      : mName(name),
        mValue(base::StringPrintf("VSYNC-%s", name), 0),
        mTraceVsync(traceVsync),
        mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration) {
    mCallbackRepeater =
            std::make_unique<CallbackRepeater>(vSyncDispatch,
                                               std::bind(&DispSyncSource::onVsyncCallback, this,
                                                         std::placeholders::_1,
                                                         std::placeholders::_2,
                                                         std::placeholders::_3),
                                               name, workDuration, readyDuration,
                                               std::chrono::steady_clock::now().time_since_epoch());
}

DispSyncSource中初始化了一些成員變數,創建了一個 對象

CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,
                     std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
                     std::chrono::nanoseconds notBefore)
          : mName(name),
            mCallback(cb), // 存儲回調函數,指向 DispSyncSource::onVsyncCallback
            mRegistration(dispatch,  //   mRegistration是一個VSyncCallbackRegistration對象,綁定了回調到CallbackRepeater::callback函數
                          std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
                                    std::placeholders::_2, std::placeholders::_3),
                          mName),
            mStarted(false),
            mWorkDuration(workDuration),
            mReadyDuration(readyDuration),
            mLastCallTime(notBefore) {}

VSyncCallbackRegistration構造函數,

VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,
                                                     VSyncDispatch::Callback const& callbackFn,
                                                     std::string const& callbackName)
      : mDispatch(dispatch),
        mToken(dispatch.registerCallback(callbackFn, callbackName)), // 註冊了回調,callbackFn指向CallbackRepeater::callback
        mValidToken(true) {}

上面的流程就可以看到:最終調用了 VSyncDispatchTimerQueue::registerCallback 函數,並且這個回調函數綁定的是 CallbackRepeater::callback

void callback(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        ...
        mCallback(vsyncTime, wakeupTime, readyTime); // mCallback 指向 DispSyncSource::onVsyncCallback
       ...
    }

DispSyncSource::onVsyncCallback繼續分發

[/frameworks/native/services/surfaceflinger/Scheduler/DispSyncSource.cpp]
void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
                                     nsecs_t readyTime) {
    VSyncSource::Callback* callback;
    {
        std::lock_guard lock(mCallbackMutex);
        callback = mCallback;
    }
    ....
    if (callback != nullptr) {
        callback->onVSyncEvent(targetWakeupTime, vsyncTime, readyTime);
    }
}

 

DispSyncSource中mCallback是誰設置的呢?指向哪裡? 答案是 EventThread ,稍後我們來看

 

Scheduler::createConnection創建完DispSyncSource後,馬上去創建了一個EventThread對象,並且把DispSyncSource對象作為參數傳遞過去了

看看EventThread的構造函數

[/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
                         android::frametimeline::TokenManager* tokenManager,
                         InterceptVSyncsCallback interceptVSyncsCallback,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction)
      : mVSyncSource(std::move(vsyncSource)), // 保存 DispVSyncSource 對象
        mTokenManager(tokenManager),
        mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
        mThreadName(mVSyncSource->getName()) {

    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");

    mVSyncSource->setCallback(this); // 為 DispVSyncSource 設置回調
    // 開啟新執行緒,執行threadMain
    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
    });
    ...
}

 

所以最終VSync事件會來到 EventThread::onVSyncEvent 中,該方法會把事件封裝後存到 mPendingEvents 並喚醒 EventThread::threadMain 做進一步的後續處理。

 

簡單總結下整個 VSync事件 回調的流程:

 

實際驗證一下,列印調用棧資訊:是不是個上面的流程圖一致 🤡

11-13 01:15:27.168   223   464 E EventThread: stackdump:#00 pc 000b49e9  /system/bin/surfaceflinger (android::impl::EventThread::onVSyncEvent(long long, long long, long long)+88)
11-13 01:15:27.168   223   464 E EventThread: stackdump:#01 pc 000b3267  /system/bin/surfaceflinger (android::scheduler::DispSyncSource::onVsyncCallback(long long, long long, long long)+122)
11-13 01:15:27.168   223   464 E EventThread: stackdump:#02 pc 000b381b  /system/bin/surfaceflinger (std::__1::__function::__func<std::__1::__bind<void (android::scheduler::DispSyncSource::*)(long long, long long, long long), android::scheduler::DispSyncSource*, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&>, std::__1::allocator<std::__1::__bind<void (android::scheduler::DispSyncSource::*)(long long, long long, long long), android::scheduler::DispSyncSource*, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&> >, void (long long, long long, long long)>::operator()(long long&&, long long&&, long long&&)+52)
11-13 01:15:27.168   223   464 E EventThread: stackdump:#03 pc 000b387b  /system/bin/surfaceflinger (android::scheduler::CallbackRepeater::callback(long long, long long, long long)+86)
11-13 01:15:27.168   223   464 E EventThread: stackdump:#04 pc 000b396f  /system/bin/surfaceflinger (std::__1::__function::__func<std::__1::__bind<void (android::scheduler::CallbackRepeater::*)(long long, long long, long long), android::scheduler::CallbackRepeater*, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&>, std::__1::allocator<std::__1::__bind<void (android::scheduler::CallbackRepeater::*)(long long, long long, long long), android::scheduler::CallbackRepeater*, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&> >, void (long long, long long, long long)>::operator()(long long&&, long long&&, long long&&)+52)
11-13 01:15:27.168   223   464 E EventThread: stackdump:#05 pc 000c3d57  /system/bin/surfaceflinger (android::scheduler::VSyncDispatchTimerQueue::timerCallback()+738)
11-13 01:15:27.168   223   464 E EventThread: stackdump:#06 pc 000c3675  /system/bin/surfaceflinger (android::scheduler::Timer::dispatch()+580)

 

 

這樣通過前面的一系列流程的跟蹤,大體理清楚了 VSync Event通過層層callback,最終來到了EventThread::onVSyncEvent 中進行處理。當然後面如何通知到 SF & APP之後再慢慢分析。

 

我們再回到SurfaceFlinger中的initScheduler方法,繼續之前的分析

SurfaceFlinger::initScheduler方法中,連續創建了2個 Connection ,一個名字是「app」,一個名字是「appSf」,每個Connection都有各自對應一個EventThread。

 

2.4 mEventQueue->initVsync 這又做了啥

mEventQueue->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
                           configs.late.sfWorkDuration);

看看initVsync的定義吧

[/frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp]
void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) {
    setDuration(workDuration);
    mVsync.tokenManager = &tokenManager;
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(dispatch, // 向 VSyncDispatch 中註冊回調,綁定到 MessageQueue::vsyncCallback 
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
}

是不是和前面講的CallbackRepeater的很相似的處理邏輯,通過構建VSyncCallbackRegistration對象,向VsyncDispatch中註冊了回調,而且名字是「sf」,這樣MessageQueue::vsyncCallback中就可以收到 vsync event了

 

實際驗證一下,列印調用棧資訊:是不是和分析一致 🤡

11-13 01:15:43.899   224   529 E SurfaceFlinger: stackdump:#00 pc 000b9837  /system/bin/surfaceflinger (android::impl::MessageQueue::vsyncCallback(long long, long long, long long)+134)
11-13 01:15:43.899   224   529 E SurfaceFlinger: stackdump:#01 pc 000b9f63  /system/bin/surfaceflinger (std::__1::__function::__func<std::__1::__bind<void (android::impl::MessageQueue::*)(long long, long long, long long), android::impl::MessageQueue*, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&>, std::__1::allocator<std::__1::__bind<void (android::impl::MessageQueue::*)(long long, long long, long long), android::impl::MessageQueue*, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&, std::__1::placeholders::__ph<3> const&> >, void (long long, long long, long long)>::operator()(long long&&, long long&&, long long&&)+52)
11-13 01:15:43.900   224   529 E SurfaceFlinger: stackdump:#02 pc 000c3ccf  /system/bin/surfaceflinger (android::scheduler::VSyncDispatchTimerQueue::timerCallback()+714)
11-13 01:15:43.900   224   529 E SurfaceFlinger: stackdump:#03 pc 000c3605  /system/bin/surfaceflinger (android::scheduler::Timer::dispatch()+580)

 

 

 

 

看到這裡,是不是就清楚了,文章開頭,dumpsys SurfaceFlinger 看到的 VSyncDispatch 中的三個回調(sf, appSf, app)是怎麼來的了

VSyncDispatch:
	Timer:
		DebugState: Waiting
	mTimerSlack: 0.50ms mMinVsyncDistance: 3.00ms
	mIntendedWakeupTime: 9223369916416.00ms from now
	mLastTimerCallback: 4215.62ms ago mLastTimerSchedule: 4215.54ms ago
	Callbacks: 三個回調
		sf:  
			workDuration: 15.67ms readyDuration: 0.00ms earliestVsync: -11799.97ms relative to now
			mLastDispatchTime: 4200.02ms ago
		appSf:
			workDuration: 16.67ms readyDuration: 15.67ms earliestVsync: -2153016.50ms relative to now
			mLastDispatchTime: 2153016.50ms ago
		app:  
			workDuration: 16.67ms readyDuration: 15.67ms earliestVsync: -4183.37ms relative to now

 

 

總結重點

收到vsync events的彙集到了兩個地方:

1. MessageQueue::vsyncCallback  ==> VSYNC-sf

2. EventThread::onVSyncEvent  ==> VSYNC-app  & VSYNC-appSf

 

有個疑問:VSyncDispatch 中的三個回調(sf, appSf, app),他們的用途又是什麼呢?或者說他們產生的回調用來驅動去做什麼事情呢?

 

三、小結

這篇文章,主要分析了VSync相關的一些初始化的過程,包括和 vsync event的產生和分發相關的組件及事件回調的流程。

當然,關於vsync的很多細節還是沒分析清楚,也有很多疑問沒解決。再接下來的文章中會再繼續研究,看看能不能得到更多的啟發與理解。

 

參考:

//juejin.cn/post/6844904013914374152

//juejin.cn/post/7045996528942448648

//blog.csdn.net/houliang120/article/details/50908098