43

Android 12(S) 图像显示系统 - SurfaceFlinger之VSync-上篇(十六) - 二的次方

 2 years ago
source link: https://www.cnblogs.com/roger-yu/p/16075956.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

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

979092-20220419093503734-1365434375.jpg

整个显示过程就是:

  • 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

对前面的流程小结一下,大概如下:

979092-20220419104611189-732228162.png

接下来我们深入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事件 回调的流程:

979092-20220419162030046-1934720951.png

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

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的很多细节还是没分析清楚,也有很多疑问没解决。再接下来的文章中会再继续研究,看看能不能得到更多的启发与理解。

https://juejin.cn/post/6844904013914374152

https://juejin.cn/post/7045996528942448648

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK