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系统进行了重构,引入了三个核心元素:VSync
、Triple Buffer
和Choreographer
。从这篇文章开始,我们就来看一看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硬件模块根据屏幕刷新率产生。VSyncTracker
、VsyncPredictor
根据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对外提供addPresentFence
addHwVsyncTimestamp
方法,把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