必读:

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并注册回调函数,如下摘录的代码:

  1. [/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
  2. void SurfaceFlinger::init() {
  3. // 创建HWComposer对象并传入一个name属性,再通过mCompositionEngine->setHwComposer设置对象属性。
  4. mCompositionEngine->setTimeStats(mTimeStats);
  5. mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
  6. mCompositionEngine->getHwComposer().setCallback(this); // 这里的this就是SurfaceFlinger对象本身,因为它实现了HWC2::ComposerCallback回调接口
  7. }

HWC2::ComposerCallback中定义了 VSYNC信号、插拔显示器等的回调事件方法,如下:

  1. [/frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h]
  2. struct ComposerCallback {
  3. virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0; // 热插拔事件
  4. virtual void onComposerHalRefresh(hal::HWDisplayId) = 0; // refresh 刷新事件
  5. virtual void onComposerHalVsync(hal::HWDisplayId, int64_t timestamp, // VSYNC信号事件
  6. std::optional<hal::VsyncPeriodNanos>) = 0;
  7. ...
  8. };

根据HWC2::ComposerCallback的设计逻辑,SurfaceFlinger::init方法中设置完HWC的回调后,会立即收到一个Hotplug事件,并在SurfaceFlinger::onComposerHalHotplug中去处理,因此流程就走到了:

  1. [/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
  2. void SurfaceFlinger::onComposerHalHotplug(hal::HWDisplayId hwcDisplayId,
  3. hal::Connection connection) {
  4. ...
  5. if (std::this_thread::get_id() == mMainThreadId) {
  6. // Process all pending hot plug events immediately if we are on the main thread.
  7. processDisplayHotplugEventsLocked(); // 主线程中去处理 hot plug evnets
  8. }
  9. }

再看processDisplayHotplugEventsLocked的代码:

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

上述代码我们只关心和VSync信后相关的逻辑,那就是调用了initShceduler

  1. [/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
  2. void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
  3. if (mScheduler) { // 判断mScheduler是否为空,避免重复初始化
  4. // In practice it's not allowed to hotplug in/out the primary display once it's been
  5. // connected during startup, but some tests do it, so just warn and return.
  6. ALOGW("Can't re-init scheduler");
  7. return;
  8. }
  9. const auto displayId = displayState.physical->id;
  10. scheduler::RefreshRateConfigs::Config config =
  11. {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
  12. .frameRateMultipleThreshold =
  13. base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
  14. // 刷新率的配置信息,里面包含了当前的屏幕刷频率。刷新周期等信息
  15. mRefreshRateConfigs =
  16. std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
  17. displayState.physical->activeMode
  18. ->getId(),
  19. config);
  20. // currRefreshRate是一个Fps Object,其中存储了刷新率fps和刷新周期period
  21. const auto currRefreshRate = displayState.physical->activeMode->getFps();
  22. mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
  23. hal::PowerMode::OFF);
  24. // mVsyncConfiguration 是一个 VsyncConfiguration object
  25. // VsyncConfiguration 类中封装了不同刷新率下的VSYNC配置信息。app phase 就是vsyncSrc偏移量,sf phase 是sfVsyncSrc偏移量,
  26. mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);
  27. // VsyncModulator object,VSYNC调制器,根据事务调度和刷新率的变化调整VSYNC偏移量。
  28. mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());
  29. // 创建Scheduler object
  30. mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
  31. const auto configs = mVsyncConfiguration->getCurrentConfigs();
  32. const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
  33. // 创建一个Connection named "app"
  34. mAppConnectionHandle =
  35. mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
  36. /*workDuration=*/configs.late.appWorkDuration,
  37. /*readyDuration=*/configs.late.sfWorkDuration,
  38. impl::EventThread::InterceptVSyncsCallback());
  39. // 创建一个Connection named "appSf"
  40. mSfConnectionHandle =
  41. mScheduler->createConnection("appSf", mFrameTimeline->getTokenManager(),
  42. /*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),
  43. /*readyDuration=*/configs.late.sfWorkDuration,
  44. [this](nsecs_t timestamp) {
  45. mInterceptor->saveVSyncEvent(timestamp);
  46. });
  47. //initVsync主要作用是绑定一个回调函数 MessageQueue::vsyncCallback 到VSyncDispatch上,回调名字"sf"
  48. mEventQueue->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
  49. configs.late.sfWorkDuration);
  50. mRegionSamplingThread =
  51. new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables());
  52. mFpsReporter = new FpsReporter(*mFrameTimeline, *this);
  53. mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId,
  54. displayState.physical->activeMode->getId(),
  55. vsyncPeriod);
  56. static auto ignorePresentFences =
  57. base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
  58. mScheduler->setIgnorePresentFences(
  59. ignorePresentFences ||
  60. getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE));
  61. }

我们可以dumpsys SurfaceFlinger看一看,VSyncDispatch上都绑定了哪些Callbacks,如下信息:有三个“sf”,"appSf", "app"是不是和我们initShceduler

代码中的逻辑冥冥之中有点呼应了...

  1. VSyncDispatch:
  2. Timer:
  3. DebugState: Waiting
  4. mTimerSlack: 0.50ms mMinVsyncDistance: 3.00ms
  5. mIntendedWakeupTime: 9223369916416.00ms from now
  6. mLastTimerCallback: 4215.62ms ago mLastTimerSchedule: 4215.54ms ago
  7. Callbacks:
  8. sf:
  9. workDuration: 15.67ms readyDuration: 0.00ms earliestVsync: -11799.97ms relative to now
  10. mLastDispatchTime: 4200.02ms ago
  11. appSf:
  12. workDuration: 16.67ms readyDuration: 15.67ms earliestVsync: -2153016.50ms relative to now
  13. mLastDispatchTime: 2153016.50ms ago
  14. app:
  15. workDuration: 16.67ms readyDuration: 15.67ms earliestVsync: -4183.37ms relative to now
  16. mLastDispatchTime: 4183.37ms ago

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

接下来我们深入initShceduler细节,看看每一步骤都具体做了什么工作呢?

2.2 创建Scheduler对象都做了啥子?

开启创建之旅....

  1. [/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
  2. void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
  3. ...
  4. // start the EventThread
  5. mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this); //在DefaultFactory中去执行创建操作
  6. ...
  7. }

DefaultFactory中也很简单,SurfaceFlinger有实现ISchedulerCallback回调方法,参数callback指向一个SurfaceFlinger对象,参数configs是刷新率的信息

  1. [ /frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp]
  2. std::unique_ptr<Scheduler> DefaultFactory::createScheduler(
  3. const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) {
  4. return std::make_unique<Scheduler>(configs, callback); // 创建Scheduler对象,callback指向一个SurfaceFlinger Object
  5. }

进到Scheduler的构造函数,三个构造函数依次调用,初始化必要成员变量。

  1. [/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
  2. Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
  3. : Scheduler(configs, callback,
  4. {.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
  5. .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
  6. }
  7. Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
  8. Options options)
  9. : Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,//createVsyncSchedule是主要的逻辑
  10. createLayerHistory(configs), options) {
  11. ...
  12. }
  13. Scheduler::Scheduler(VsyncSchedule schedule, const scheduler::RefreshRateConfigs& configs,
  14. ISchedulerCallback& schedulerCallback,
  15. std::unique_ptr<LayerHistory> layerHistory, Options options)
  16. : mOptions(options),
  17. mVsyncSchedule(std::move(schedule)),
  18. mLayerHistory(std::move(layerHistory)),
  19. mSchedulerCallback(schedulerCallback),
  20. mRefreshRateConfigs(configs),
  21. mPredictedVsyncTracer(
  22. base::GetBoolProperty("debug.sf.show_predicted_vsync", false)
  23. ? std::make_unique<PredictedVsyncTracer>(*mVsyncSchedule.dispatch)
  24. : nullptr) {
  25. mSchedulerCallback.setVsyncEnabled(false);// 注意这里,设置了 VSync Enable False,关闭了硬件VSync
  26. }

Scheduler构造函数中,最重要的一个步骤就是去调用了createVsyncSchedule方法,这是一个核心方法,在其中创建和初始化了和VSync信号产生、分发相关的类对象和运行逻辑。

本文作者@二的次方  2022-04-18 发布于博客园

  1. [/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
  2. Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(bool supportKernelTimer) {
  3. auto clock = std::make_unique<scheduler::SystemClock>();
  4. auto tracker = createVSyncTracker(); // 创建VSyncTracker对象
  5. auto dispatch = createVSyncDispatch(*tracker); // 创建VSyncDispatch对象
  6. // TODO(b/144707443): Tune constants.
  7. constexpr size_t pendingFenceLimit = 20;
  8. auto controller = // 创建VSyncReactor对象
  9. std::make_unique<scheduler::VSyncReactor>(std::move(clock), *tracker, pendingFenceLimit,
  10. supportKernelTimer);
  11. return {std::move(controller), std::move(tracker), std::move(dispatch)}; // 把tracker,dispatch,controller封装在一个VsyncSchedule strcut中
  12. }

createVsyncSchedule方法最终返回了一个VsyncSchedule结构体对象。VsyncSchedule是一个结构体类型,含有三个成员变量:controller、tracker、dispatch,这三个成员在 VSync机制中分别发挥不同作用,等到下面再分析。

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

2.2.1 先看创建VSyncTracker做了啥?

  1. [/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
  2. std::unique_ptr<scheduler::VSyncTracker> createVSyncTracker() {
  3. // TODO(b/144707443): Tune constants.
  4. constexpr int kDefaultRate = 60;
  5. constexpr auto initialPeriod = std::chrono::duration<nsecs_t, std::ratio<1, kDefaultRate>>(1);
  6. constexpr nsecs_t idealPeriod =
  7. std::chrono::duration_cast<std::chrono::nanoseconds>(initialPeriod).count();
  8. constexpr size_t vsyncTimestampHistorySize = 20;
  9. constexpr size_t minimumSamplesForPrediction = 6; // 为了预测、模拟VSync最少需要采样的个数
  10. constexpr uint32_t discardOutlierPercent = 20;
  11. return std::make_unique<scheduler::VSyncPredictor>(idealPeriod, vsyncTimestampHistorySize,
  12. minimumSamplesForPrediction,
  13. discardOutlierPercent);
  14. }

实际创建的是一个实现类VsyncPredictor对象,VSyncTracker是一个基于历史Vsync时间数据提供未来Vsync信号时间估计的接口,VsyncPredictor实现了VSyncTracker中的方法。

  1. [/frameworks/native/services/surfaceflinger/Scheduler/VSyncTracker.h]
  2. class VSyncTracker { //虚基类,接口类,VSyncTracker是一个基于历史Vsync时间数据提供未来Vsync信号时间估计的接口。
  3. [ /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h]
  4. class VSyncPredictor : public VSyncTracker { //实现VSyncTracker的方法

其中有2个方法,添加 采样的vsync 时间戳,一般来自HWVsync,基于这些Vsync时间数据来训练一个模拟的VSync模型,从而达到预测未来VSync时间的目的。

  1. /*
  2. * Adds a known timestamp from a vsync timing source (HWVsync signal, present fence)
  3. * to the model.
  4. */
  5. virtual bool addVsyncTimestamp(nsecs_t timestamp) = 0;
  6. /*
  7. * Access the next anticipated vsync time such that the anticipated time >= timePoint.
  8. * This will always give the best accurate at the time of calling; multiple
  9. * calls with the same timePoint might give differing values if the internal model
  10. * is updated.
  11. */
  12. virtual nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const = 0;

至于如何计算、预测的,本文不做讲解。


我的理解是:VSync信号是由HWC硬件模块根据屏幕刷新率产生。VSyncTrackerVsyncPredictor根据HWC产生的硬件VSync信号,训练了一个模拟的VSync事件源,可以预测vsync事件的时间点。


2.2.2 创建VSyncDispatch做了啥子呢?

先瞅瞅代码吧,很简单创建了一个VSyncDispatchTimerQueue对象,这又是个什么鬼?

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

先看看定义吧

  1. [/frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatch.h]
  2. class VSyncDispatch { // 用于分发和系统VSync事件相关的回调事件
  3. [/frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp]
  4. // VSyncDispatchTimerQueue是一个类,它将使用单个计时器队列按照VSyncDispatch接口调度回调。
  5. class VSyncDispatchTimerQueue : public VSyncDispatch {

根据代码注释和基本的逻辑,我大概理解的是:

VSyncDispatchTimerQueue(VSyncDispatch)负责分发VSync回调事件,需要接收VSync事件的模块可以通过registerCallback向其中注册回调函数,所有的回调都保存在了CallbackMap mCallbacks,当到了VSync发生的时间就会遍历注册的回调,把VSync事件分发出去。

2.2.3 还创建了一个VsyncController对象

  1. auto controller =
  2. std::make_unique<scheduler::VSyncReactor>(std::move(clock), *tracker, pendingFenceLimit,
  3. 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的调用栈信息

  1. 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)
  2. 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)
  3. 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)
  4. 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是何方神圣?

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

先看看代码吧

  1. Scheduler::ConnectionHandle Scheduler::createConnection(
  2. const char* connectionName, frametimeline::TokenManager* tokenManager,
  3. std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
  4. impl::EventThread::InterceptVSyncsCallback interceptCallback) {
  5. auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration); //创建了一个DispSyncSource对象
  6. auto throttleVsync = makeThrottleVsyncCallback();
  7. auto getVsyncPeriod = makeGetVsyncPeriodFunction();
  8. auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager, // 创建了一个EventThread对象
  9. std::move(interceptCallback),
  10. std::move(throttleVsync),
  11. std::move(getVsyncPeriod));
  12. return createConnection(std::move(eventThread));
  13. }

上面的方法中干了两件大事:创建DispSyncSource对象和EventThread对象

创建DispSyncSource对象做了啥?

  1. std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
  2. const char* name, std::chrono::nanoseconds workDuration,
  3. std::chrono::nanoseconds readyDuration, bool traceVsync) {
  4. // mVsyncSchedule.dispatch 就是在Scheduler创建时,创建的VSyncDispatchTimerQueue对象
  5. return std::make_unique<scheduler::DispSyncSource>(*mVsyncSchedule.dispatch, workDuration,
  6. readyDuration, traceVsync, name);
  7. }

再看DispSyncSource的构造函数:

  1. DispSyncSource::DispSyncSource(scheduler::VSyncDispatch& vSyncDispatch,
  2. std::chrono::nanoseconds workDuration,
  3. std::chrono::nanoseconds readyDuration, bool traceVsync,
  4. const char* name)
  5. : mName(name),
  6. mValue(base::StringPrintf("VSYNC-%s", name), 0),
  7. mTraceVsync(traceVsync),
  8. mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
  9. mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
  10. mReadyDuration(readyDuration) {
  11. mCallbackRepeater =
  12. std::make_unique<CallbackRepeater>(vSyncDispatch,
  13. std::bind(&DispSyncSource::onVsyncCallback, this,
  14. std::placeholders::_1,
  15. std::placeholders::_2,
  16. std::placeholders::_3),
  17. name, workDuration, readyDuration,
  18. std::chrono::steady_clock::now().time_since_epoch());
  19. }

DispSyncSource中初始化了一些成员变量,创建了一个 对象

  1. CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,
  2. std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
  3. std::chrono::nanoseconds notBefore)
  4. : mName(name),
  5. mCallback(cb), // 存储回调函数,指向 DispSyncSource::onVsyncCallback
  6. mRegistration(dispatch, // mRegistration是一个VSyncCallbackRegistration对象,绑定了回调到CallbackRepeater::callback函数
  7. std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
  8. std::placeholders::_2, std::placeholders::_3),
  9. mName),
  10. mStarted(false),
  11. mWorkDuration(workDuration),
  12. mReadyDuration(readyDuration),
  13. mLastCallTime(notBefore) {}

VSyncCallbackRegistration构造函数,

  1. VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,
  2. VSyncDispatch::Callback const& callbackFn,
  3. std::string const& callbackName)
  4. : mDispatch(dispatch),
  5. mToken(dispatch.registerCallback(callbackFn, callbackName)), // 注册了回调,callbackFn指向CallbackRepeater::callback
  6. mValidToken(true) {}

上面的流程就可以看到:最终调用了 VSyncDispatchTimerQueue::registerCallback 函数,并且这个回调函数绑定的是 CallbackRepeater::callback

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

DispSyncSource::onVsyncCallback继续分发

  1. [/frameworks/native/services/surfaceflinger/Scheduler/DispSyncSource.cpp]
  2. void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
  3. nsecs_t readyTime) {
  4. VSyncSource::Callback* callback;
  5. {
  6. std::lock_guard lock(mCallbackMutex);
  7. callback = mCallback;
  8. }
  9. ....
  10. if (callback != nullptr) {
  11. callback->onVSyncEvent(targetWakeupTime, vsyncTime, readyTime);
  12. }
  13. }

DispSyncSource中mCallback是谁设置的呢?指向哪里? 答案是 EventThread ,稍后我们来看

Scheduler::createConnection创建完DispSyncSource后,马上去创建了一个EventThread对象,并且把DispSyncSource对象作为参数传递过去了

看看EventThread的构造函数

  1. [/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
  2. EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
  3. android::frametimeline::TokenManager* tokenManager,
  4. InterceptVSyncsCallback interceptVSyncsCallback,
  5. ThrottleVsyncCallback throttleVsyncCallback,
  6. GetVsyncPeriodFunction getVsyncPeriodFunction)
  7. : mVSyncSource(std::move(vsyncSource)), // 保存 DispVSyncSource 对象
  8. mTokenManager(tokenManager),
  9. mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
  10. mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
  11. mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
  12. mThreadName(mVSyncSource->getName()) {
  13. LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
  14. "getVsyncPeriodFunction must not be null");
  15. mVSyncSource->setCallback(this); // 为 DispVSyncSource 设置回调
  16. // 开启新线程,执行threadMain
  17. mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
  18. std::unique_lock<std::mutex> lock(mMutex);
  19. threadMain(lock);
  20. });
  21. ...
  22. }

所以最终VSync事件会来到 EventThread::onVSyncEvent 中,该方法会把事件封装后存到 mPendingEvents 并唤醒 EventThread::threadMain 做进一步的后续处理。

简单总结下整个 VSync事件 回调的流程:

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

  1. 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)
  2. 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)
  3. 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)
  4. 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)
  5. 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)
  6. 11-13 01:15:27.168 223 464 E EventThread: stackdump:#05 pc 000c3d57 /system/bin/surfaceflinger (android::scheduler::VSyncDispatchTimerQueue::timerCallback()+738)
  7. 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 这又做了啥

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

看看initVsync的定义吧

  1. [/frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp]
  2. void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
  3. frametimeline::TokenManager& tokenManager,
  4. std::chrono::nanoseconds workDuration) {
  5. setDuration(workDuration);
  6. mVsync.tokenManager = &tokenManager;
  7. mVsync.registration = std::make_unique<
  8. scheduler::VSyncCallbackRegistration>(dispatch, // 向 VSyncDispatch 中注册回调,绑定到 MessageQueue::vsyncCallback
  9. std::bind(&MessageQueue::vsyncCallback, this,
  10. std::placeholders::_1,
  11. std::placeholders::_2,
  12. std::placeholders::_3),
  13. "sf");
  14. }

是不是和前面讲的CallbackRepeater的很相似的处理逻辑,通过构建VSyncCallbackRegistration对象,向VsyncDispatch中注册了回调,而且名字是“sf”,这样MessageQueue::vsyncCallback中就可以收到 vsync event了

实际验证一下,打印调用栈信息:是不是和分析一致

  1. 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)
  2. 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)
  3. 11-13 01:15:43.900 224 529 E SurfaceFlinger: stackdump:#02 pc 000c3ccf /system/bin/surfaceflinger (android::scheduler::VSyncDispatchTimerQueue::timerCallback()+714)
  4. 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)是怎么来的了

  1. VSyncDispatch:
  2. Timer:
  3. DebugState: Waiting
  4. mTimerSlack: 0.50ms mMinVsyncDistance: 3.00ms
  5. mIntendedWakeupTime: 9223369916416.00ms from now
  6. mLastTimerCallback: 4215.62ms ago mLastTimerSchedule: 4215.54ms ago
  7. Callbacks: 三个回调
  8. sf:
  9. workDuration: 15.67ms readyDuration: 0.00ms earliestVsync: -11799.97ms relative to now
  10. mLastDispatchTime: 4200.02ms ago
  11. appSf:
  12. workDuration: 16.67ms readyDuration: 15.67ms earliestVsync: -2153016.50ms relative to now
  13. mLastDispatchTime: 2153016.50ms ago
  14. app:
  15. 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

Android 12(S) 图像显示系统 - SurfaceFlinger之VSync-上篇(十六)的更多相关文章

  1. Android 12(S) 图像显示系统 - SurfaceFlinger 之 VSync - 中篇(十七)

    必读: Android 12(S) 图像显示系统 - 开篇 1 前言 这一篇文章,将继续讲解有关VSync的知识,前一篇文章 Android 12(S) 图像显示系统 - SurfaceFlinger ...

  2. Android 12(S) 图像显示系统 - SurfaceFlinger GPU合成/CLIENT合成方式 - 随笔1

    必读: Android 12(S) 图像显示系统 - 开篇 一.前言 SurfaceFlinger中的图层选择GPU合成(CLIENT合成方式)时,会把待合成的图层Layers通过renderengi ...

  3. Android 12(S) 图像显示系统 - drm_hwcomposer 简析(上)

    必读: Android 12(S) 图像显示系统 - 开篇 前言 Android源码中有包含drm_hwcomposer:/external/drm_hwcomposer/ drm_hwcompose ...

  4. Android 12(S) 图像显示系统 - GraphicBuffer同步机制 - Fence

    必读: Android 12(S) 图像显示系统 - 开篇 一.前言 前面的文章中讲解Android BufferQueue的机制时,有遇到过Fence,但没有具体讲解.这篇文章,就针对Fence这种 ...

  5. Android 12(S) 图像显示系统 - 基础知识之 BitTube

    必读: Android 12(S) 图像显示系统 - 开篇 一.基本概念 在Android显示子系统中,我们会看到有使用BitTube来进行跨进程数据传递.BitTube的实现很简洁,就是一对&quo ...

  6. Android 12(S) 图像显示系统 - HWC HAL 初始化与调用流程

    必读: Android 12(S) 图像显示系统 - 开篇 接口定义 源码位置:/hardware/interfaces/graphics/composer/ 在源码目录下可以看到4个版本的HIDL ...

  7. Android 12(S) 图像显示系统 - drm_hwcomposer 简析(下)

    必读: Android 12(S) 图像显示系统 - 开篇 合成方式 合成类型的定义:/hardware/interfaces/graphics/composer/2.1/IComposerClien ...

  8. Android 12(S) 图形显示系统 - SurfaceFlinger的启动和消息队列处理机制(四)

    1 前言 SurfaceFlinger作为Android图形显示系统处理逻辑的核心单元,我们有必要去了解其是如何启动,初始化及进行消息处理的.这篇文章我们就来简单分析SurfaceFlinger这个B ...

  9. Android 12(S) 图形显示系统 - BufferQueue/BLASTBufferQueue之初识(六)

    题外话 你有没有听见,心里有一声咆哮,那一声咆哮,它好像在说:我就是要从后面追上去! 写文章真的好痛苦,特别是自己对这方面的知识也一知半解就更加痛苦了.这已经是这个系列的第六篇了,很多次都想放弃了,但 ...

随机推荐

  1. jinja2.exceptions.TemplateNotFound 报错处理

    一.检查模板文件夹是否正确. 遇到这个问题,首先需要检查你的模板文件夹命名是否规范,Flask默认会在工程下寻找templates文件夹,这个是默认配置,不能写成template或者其他名字.当然,如 ...

  2. leetcode-3无重复字符的最长子串

    题目原题: 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 ...

  3. 对原型链的理解?prototype上都有哪些属性?

    在js里,继承机制是原型继承.继承的起点是 对象的原型(Object prototype). 一切皆为对象,只要是对象,就会有 proto 属性,该属性存储了指向其构造的指针. Object prot ...

  4. C# winform自己的窗体不抢夺其他窗体的光标

    在你的form里加入: protected override CreateParams CreateParams { get { var result = base.CreateParams; ; r ...

  5. java中线程池创建的几种方式

    java中创建线程池的方式一般有两种: 通过Executors工厂方法创建 通过new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize ...

  6. OGNL(Object-Graph Navigation Language)使用

    OGNL表达式:https://www.jianshu.com/p/6bc6752d11f4 Apache OGNL:http://commons.apache.org/proper/commons- ...

  7. 运筹学之"概率"和"累计概率"和"谁随机数"

    概率 = 2/50 = 0.2 累计概率 = 上个概率加本次概率 案例1 概率=销量天数 / 天数 = 2 /100 = 0.02 累计概率 = 上个概率加本次概率 = 0.02 +0.03 = 0. ...

  8. C++ | 简单工厂模式 | 复数计算器

    简单工厂模式最直观的一个应用便是实现一个计算器的程序. 比如,公司让你给计算器添加一个幂运算的功能,你只需要设计一个幂运算的类,并实现幂运算的逻辑,然后让该类继承自运算类即可. 简单工厂模式: 简单工 ...

  9. 什么是pandas

  10. 从ES6重新认识JavaScript设计模式(三): 建造者模式

    1 什么是建造者模式? 建造者模式(Builder)是将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示. 建造者模式的特点是分步构建一个复杂的对象,可以用不同组合或顺序建造出不 ...