其他分享
首页 > 其他分享> > Android 12(S) 图像显示系统 - SurfaceFlinger之VSync-上篇(十六)

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的实现机制。

关于屏幕刷新机制,有一张很经典的图片:

整个显示过程就是:

如果屏幕的刷新率是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事件 回调的流程:

 

实际验证一下,打印调用栈信息:是不是个上面的流程图一致

标签:std,__,12,const,Scheduler,ms,long,SurfaceFlinger,VSync
来源: https://www.cnblogs.com/roger-yu/p/16075956.html