1. 前言
忽然有一天,我想要做一件事:去代码中去验证那些曾经被"灌输"的理论。
-- 服装学院的IT男
本篇为 VSync 系列的第二篇,主要介绍"app appsf sf"是如何注册回调到 VSyncDispatchTimerQueue 下的 mCallbacks 中的。
本系列为之前学习 SurfaceFlinger 整理的一些笔记,现在分享出来,希望能帮助到有需要的同学。代码基于 Android 13,虽然很多逻辑与最新源码有所不同,但总体思路依然不变,不影响对 VSync 整体逻辑的理解。
VSync 系列目录:
正文
在分析之前,我们需要先了解 SurfaceFlinger::initScheduler 方法。
scss
# SurfaceFlinger.cpp
void SurfaceFlinger::initScheduler(const sp<DisplayDevice>& display) {
// 避免重复初始化
if (mScheduler) {
mScheduler->setRefreshRateConfigs(display->holdRefreshRateConfigs());
return;
}
// 是一个Fps对象,其中存储了刷新率fps和刷新周期period
const auto currRefreshRate = display->getActiveMode()->getFps();
mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
hal::PowerMode::OFF);
// 封装了不同刷新率下的VSync配置信息
mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);
mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());
......
// 重点* 1.1 创建 Scheduler
mScheduler = std::make_unique<scheduler::Scheduler>(static_cast<ICompositor&>(*this),
static_cast<ISchedulerCallback&>(*this),
features);
{
auto configs = display->holdRefreshRateConfigs();
if (configs->kernelIdleTimerController().has_value()) {
features |= Feature::kKernelIdleTimer;
}
// 重点* 1.2 初始化 VsyncSchedule
mScheduler->createVsyncSchedule(features);
mScheduler->setRefreshRateConfigs(std::move(configs));
}
setVsyncEnabled(false);
mScheduler->startTimers();
// 当前设备下,SurfaceFlinger 相关的配置
const auto configs = mVsyncConfiguration->getCurrentConfigs();
const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
// 重点* 2.1 app 注册回调
mAppConnectionHandle =
mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
/*workDuration=*/configs.late.appWorkDuration,
/*readyDuration=*/configs.late.sfWorkDuration,
impl::EventThread::InterceptVSyncsCallback());
// 重点* 2.2 appSf 注册回调
mSfConnectionHandle =
mScheduler->createConnection("appSf", mFrameTimeline->getTokenManager(),
/*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),
/*readyDuration=*/configs.late.sfWorkDuration,
[this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
// 重点* 2.3 sf 注册回调
mScheduler->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
configs.late.sfWorkDuration);
......
}
本篇需要关注"2.1 2.2 2.3"这三个流程,其中 appsf 和 app 的注册回调的调用是一样的,以 app 为例分析即可。
本篇目的:
-
- app 和 appsf 是如何注册到 mCallbacks
-
- 各自传递的 VSync 回调是什么。
本篇分析的代码中会出现多个回调,很容易就绕晕了,建议心里就牢记着两个回调:分别是定时结束后如何回调给应用和 SurfaceFlinger 的。
1 app appsf 向 VsyncDispatch 注册回调
rust
# Scheduler.cpp
// connectionName 为对应的名字,这里就是 "app" 或 "appSf"
ConnectionHandle Scheduler::createConnection(
const char* connectionName, frametimeline::TokenManager* tokenManager,
std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
// 1. 构建出 DispSyncSource 对象
auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration);
auto throttleVsync = makeThrottleVsyncCallback();
auto getVsyncPeriod = makeGetVsyncPeriodFunction();
// 2. 创建出对应的线程 "app" 和 "appsf"
auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
std::move(interceptCallback),
std::move(throttleVsync),
std::move(getVsyncPeriod));
// 3.构建一个Connection保存并返回
return createConnection(std::move(eventThread));
}
这里有三个步骤:
-
- 创建 DispSyncSource
-
- 创建 EventThread
-
- 构建 Connection 保存并返回
比较重要的是 DispSyncSource 和 EventThread 的创建,一个是 app 的 VSync 信号源,1个是处理 VSYNC-app 与具体应用工作的。
1.1 DispSyncSource 的创建
rust
# Scheduler.cpp
std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
const char* name, std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration, bool traceVsync) {
// 创建 DispSyncSource
return std::make_unique<scheduler::DispSyncSource>(mVsyncSchedule->getDispatch(),
mVsyncSchedule->getTracker(), workDuration,
readyDuration, traceVsync, name);
}
-
- 实际返回的是 DispSyncSource,说明其是 VSyncSource 的子类
-
- 传递了 VsyncDispatch 和 VsyncTracker,说明这个类也会处理 VSync 相关逻辑
-
- 传递了 name,这个对象不是单例,而且只有 "app"和"appsf",说明这个类服务于应用相关的 VSync
注意这里还传递了 workDuration 和 readyDuration 两个关键的时间进去,先看一下 DispSyncSource 的头文件。

对 DispSyncSource 有了个大概的了解后看看其构造:
less
# DispSyncSource.cpp
DispSyncSource::DispSyncSource(VSyncDispatch& vSyncDispatch, VSyncTracker& vSyncTracker,
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration, bool traceVsync,
const char* name)
: mName(name), // 当前DispSyncSource的名字
mValue(base::StringPrintf("VSYNC-%s", name), 0), // trace 的值
mTraceVsync(traceVsync),
mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
mVSyncTracker(vSyncTracker),
mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
mReadyDuration(readyDuration) {
// 构建CallbackRepeater
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());
}
-
- 这里看到 trace 的名字是 ("VSYNC-%s", name),和 VSYNC-app,VSYNC-appsf 对上了
-
- 对 mName,VSyncTracker 以及 workDuration,readyDuration 等变量做初始化赋值
-
- 初始化 mCallbackRepeater (构建 CallbackRepeater )
其他的几个成员变量都是传参过来的,mCallbackRepeater 则是需要构建,注意这里传递过去的回调是 DispSyncSource::onVsyncCallback ,还有其他参数也很重要。
1.1.1 回调:DispSyncSource::onVsyncCallback
本篇分析的就是这些回调的关系,所以代码中出现的回调肯定是要重点看看的。
arduino
# DispSyncSource.cpp
// 重点* 1. 设置mCallback值
void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
std::lock_guard lock(mCallbackMutex);
mCallback = callback;
}
// 回调
void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
nsecs_t readyTime) {
VSyncSource::Callback* callback;
{
std::lock_guard lock(mCallbackMutex);
// mCallback 赋值给 callback
callback = mCallback;
}
// 重点* 2. 控制 Trace 的值
if (mTraceVsync) {
mValue = (mValue + 1) % 2;
}
if (callback != nullptr) {
// 重点* 3. 执行Vsync 回调
callback->onVSyncEvent(targetWakeupTime, {vsyncTime, readyTime});
}
}
这里有三个重点:
-
- mCallback 的类型是 VSyncSource::Callback ,在头文件定义,在 DispSyncSource::setCallback 赋值,这个方法调用的地方在后面构建 EventThread 的时候
-
- 在 Trace 上看到 VSYNC-app VSYNC-appsf 起伏的原因就在这,我们知道一次起伏代表来了一次 VSync ,所以 DispSyncSource::onVsyncCallback 的执行就说明触发了 VSync 。
-
- 这里执行的其实是 EventThread::onVSyncEvent 方法,也就是将 VSync 发送到 EventThread 中做后续处理。
可以暂且就把 EventThread 这个类当成应用接收 VSync 的类。
SurfaceFlinger 有一篇很经典的文章(www.jianshu.com/p/5e9c558d1... VsyncDispatch 与 EventThread 之间的桥梁"就是这个意思。
VsyncDispatch 可以理解为 SW-VSYNC 产生的地方,然后分别要给到应用和 SurfaceFlinger ,应用这边的类是 EventThread ,这么一看 DispSyncSource 确实是"桥梁"。

DispSyncSource 下的 mCallback 变量也很重要,上面的截图里有介绍。
1.2 CallbackRepeater 的构建
CallbackRepeater 定义在 DispSyncSource.cpp 下,说明其也是服务于 DispSyncSource 的。 看类名像是处理回调的,构建的时候也确实传递了 DispSyncSource::onVsyncCallback 。
php
# DispSyncSource.cpp
class CallbackRepeater {
public:
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
// 构造 VSyncCallbackRegistration
mRegistration(dispatch,
std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3),
mName),
mStarted(false),
mWorkDuration(workDuration), // workDuration
mReadyDuration(readyDuration), // readyDuration
mLastCallTime(notBefore) {}
}
这里又有两个回调相关的逻辑:
-
- 参数 cb 是 VSyncDispatch::Callback 类型,看到传递过来的时候是将 DispSyncSource::onVsyncCallback 和 DispSyncSource 构造出来的对象,现在将其赋值给了 mCallback
-
- 触发构建 VSyncCallbackRegistration,传递了 CallbackRepeater::callback
这边也有两个疑问:
-
- 这里的 mCallback 又是什么?
-
- 这里的 mCallback 和 CallbackRepeater::callback 又有什么联系?
1.2.1 CallbackRepeater下的mCallback是什么
这里的 mCallback 是 VSyncDispatch::Callback 类型
php
# DispSyncSource.cpp
class CallbackRepeater {
private:
......
// mCallback 的定义
scheduler::VSyncDispatch::Callback mCallback;
......
};
看看 VSyncDispatch::Callback 的定义:
vbnet
# VSyncDispatch.h
class VSyncDispatch {
public:
* A callback that can be registered to be awoken at a given time relative to a vsync event.
* VSync 时间,看传值好像是上一次的(不确定是这次还是上次)
* \param [in] vsyncTime: The timestamp of the vsync the callback is for.
* 唤醒时间,定时器结束时间然后开始产生VSync
* \param [in] targetWakeupTime: The timestamp of intended wakeup time of the cb.
* 应用这一帧绘制完成的时间,同时也是SF开始合成的时间
* \param [in] readyTime: The timestamp of intended time where client needs to finish
* its work by.
*/
// 定义Callback类型别名
using Callback =
std::function<void(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime)>;
......
}
说明这个 Callback 是一个 VSync 来的回调函数,里面还有3个时间。 在结合上面赋值的代码,也就是说执行这个 mCallback 的时候就会执行到 DispSyncSource::onVsyncCallback 方法(3个参数也对上了)。
1.2.2 CallbackRepeater下的mCallback和CallbackRepeater::callback的联系
arduino
# DispSyncSource.cpp
class CallbackRepeater {
......
private:
void callback(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
......
// 重点* 1. 间接执行 DispSyncSource::onVsyncCallback
mCallback(vsyncTime, wakeupTime, readyTime);
{
std::lock_guard lock(mMutex);
// 如果处于关闭状态则返回
if (!mStarted) {
ATRACE_NAME("callback return not mRegistration.schedule");
return;
}
// 重点* 2. 请求 VSync
auto const scheduleResult =
mRegistration.schedule({.workDuration = mWorkDuration.count(),
.readyDuration = mReadyDuration.count(),
.earliestVsync = vsyncTime});
}
}
}
执行 CallbackRepeater::callback 的时候会做两件事:
-
- 执行 mCallback 然后会触发 DispSyncSource::onVsyncCallback 的执行
-
- 如果 DispSyncSource 还处于打开状态的话,则触发申请下一次的 VSync 的申请
这两步都很重要,一个是触发 VSync 的分发一个是触发下一次的申请(mStarted = true 的话)。
那么当前问题的答案就是:CallbackRepeater::callback 执行的时候会触发 mCallback 的执行,也就执行到了 DispSyncSource::onVsyncCallback 。
1.3 VSyncCallbackRegistration 的创建
回到主流程继续看 VSyncCallbackRegistration 的创建,VSyncCallbackRegistration 的定义在也是在 VSyncDispatch 头文件中,代码如下
arduino
# VSyncDispatch.h
/*
* Helper class to operate on registered callbacks. It is up to user of the class to ensure
* that VsyncDispatch lifetime exceeds the lifetime of VSyncCallbackRegistation.
*/
class VSyncCallbackRegistration {
public:
......
// See documentation for VSyncDispatch::schedule.
ScheduleResult schedule(VSyncDispatch::ScheduleTiming scheduleTiming);
// See documentation for VSyncDispatch::cancel.
CancelResult cancel();
private:
std::reference_wrapper<VSyncDispatch> mDispatch;
VSyncDispatch::CallbackToken mToken;
bool mValidToken;
};
根据注释,这个类是一个 VSyncDispatch 的帮助类,主要是有个 schedule 和 cancel 2个方法,分别对应应用请求和取消 VSync ,看注释调用的还是 VSyncDispatch 对应的方法。另外还有几个对象也要留意。
回到代码流程,触发 VSyncCallbackRegistration 构建的地方是在 VSyncDispatchTimerQueue.cpp 文件中,代码如下:
css
# VSyncDispatchTimerQueue.cpp
VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,
VSyncDispatch::Callback callback,
std::string callbackName)
: mDispatch(dispatch),
mToken(dispatch.registerCallback(std::move(callback), std::move(callbackName))),
mValidToken(true) {}
-
- mDispatch 赋值初始化
-
- 执行 VSyncDispatchTimerQueue::registerCallback 方法
根据之前的代码调用,这里的callback就是CallbackRepeater::callback。现在又作为参数传递到 VSyncDispatchTimerQueue::registerCallback 方法中。
目前涉及到这几个类的类图关系如下:

其中 VSyncCallbackRegistration 也持有 VSyncDispatch 的对象,而 VSyncDispatch 的类图之前也画过了。
如果把他们集合起来,就有下面这样一个关系:

1.4 app,appsf 最终的注册(VSyncDispatchTimerQueue::registerCallback)
继续回到代码流程,VSyncDispatchTimerQueue 是 VSyncDispatch 子类,其实现了 registerCallback 方法。
c
# VSyncDispatchTimerQueue.cpp
VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Callback callback, std::string callbackName) {
std::lock_guard lock(mMutex);
return CallbackToken{
mCallbacks
.emplace(++mCallbackToken,
std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
std::move(callback),
mMinVsyncDistance))
.first->first};
}
-
- 构建 VSyncDispatchTimerQueueEntry 对象,三个回调(app, appsf, sf)都是其对象
-
- 添加到 mCallbacks 中,等 SW-VSYNC 来了就会遍历这个集合里的三个 VSyncDispatchTimerQueueEntry 对象把 SW-Vsync 进行细分。
-
- 这里的回调 callback 是 CallbackRepeater::callback
VSyncDispatchTimerQueueEntry 的构造方法如下:
c
# VSyncDispatchTimerQueue.cpp
VSyncDispatchTimerQueueEntry::VSyncDispatchTimerQueueEntry(std::string name,
VSyncDispatch::Callback callback,
nsecs_t minVsyncDistance)
: mName(std::move(name)),
mCallback(std::move(callback)),
mMinVsyncDistance(minVsyncDistance) {}
# VSyncDispatchTimerQueue.h
class VSyncDispatchTimerQueueEntry {
......
private:
const std::string mName;
const VSyncDispatch::Callback mCallback;
}
这里看到 VSyncDispatchTimerQueueEntry 下又有一个 mCallback 是 VSyncDispatch::Callback 类型,根据传值是执行的 CallbackRepeater::callback 。
当定时结束执行 VSyncDispatchTimerQueue::timerCallback 来产生 VSync 的时候,本质上执行的就是 VSyncDispatchTimerQueueEntry::callback 方法。
arduino
# VSyncDispatchTimerQueue.cpp
// 定时结束执行
void VSyncDispatchTimerQueue::timerCallback() {
....... // 遍历 mCallbacks 发送 VSync
//本质就是执行对应的 VSyncDispatchTimerQueueEntry::callback
}
void VSyncDispatchTimerQueueEntry::callback(nsecs_t vsyncTimestamp, nsecs_t wakeupTimestamp,
nsecs_t deadlineTimestamp) {
......
// 实际上调的是mCallback ,构建时赋值
mCallback(vsyncTimestamp, wakeupTimestamp, deadlineTimestamp);
std::lock_guard<std::mutex> lk(mRunningMutex);
mRunning = false;
mCv.notify_all();
}
可以看到,就是触发了这个 mCallback ,根据之前的的代码逻辑,会执行到 DispSyncSource::onVsyncCallback ,进而执行到 EventThread::onVSyncEvent 。
1.5 app appsf 线程的创建
前面的分析都是在 Scheduler::createConnection 方法中执行 Scheduler::makePrimaryDispSyncSource 的调用链,在执行完这个方法后还会执行 EventThread 的创建。 看名字是要创建一个线程了,代码逻辑如下:
scss
# EventThread.cpp
EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource,
android::frametimeline::TokenManager* tokenManager,
InterceptVSyncsCallback interceptVSyncsCallback,
ThrottleVsyncCallback throttleVsyncCallback,
GetVsyncPeriodFunction getVsyncPeriodFunction)
: mVSyncSource(std::move(vsyncSource)), // 1. 初始化mVSyncSource
mTokenManager(tokenManager),
mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)),
mThreadName(mVSyncSource->getName()) { // 2.1 线程名变量赋值
LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
"getVsyncPeriodFunction must not be null");
// 3. 设置回调 DispSyncSource
mVSyncSource->setCallback(this);
// 4. 创建线程
mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
threadMain(lock);
});
// 2.2 设置线程名
pthread_setname_np(mThread.native_handle(), mThreadName);
......
}
这里有四个重点:
-
- EventThread 内也有 DispSyncSource 的对象
-
- 获取线程名并设置给当前线程,也就是"app"和"appsf"
-
- 调用 DispSyncSource::setCallback 把 EventThread::onVSyncEvent 作为回调传递到 DispSyncSource 中
-
- 创建并启动线程,内部执行 threadMain 方法,这个方法也是后面应用端申请 Vsync 的核心方法。
可以看到 EventThread 下启动了自己的线程,命名就是"app"和"appsf",这个通过shell 命令也能确认。

除了线程,还要再看一下之前提到的 DispSyncSource::setCallback 方法,因为这个方法才是真正处理 VSYNC-app 和 VSYNC-appsf 的地方。
php
# DispSyncSource.cpp
// 定义回调
scheduler::VSyncDispatch::Callback mCallback;
void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
std::lock_guard lock(mCallbackMutex);
// 赋值
mCallback = callback;
}
现在就把所有的回调都串起来了。
根据分析,这里的 DispSyncSource::setCallback 其实就是把 EventThread::onVSyncEvent 设置给了 DispSyncSource 下的 mCallback
这里可能会好奇,参数 callback 是 VSyncSource::Callback 类型,怎么可以传 EventThread::onVSyncEvent 呢? 这个在 EventThread 头文件里有注释:
arduino
# EventThread.h
class EventThread : public android::EventThread, private VSyncSource::Callback {
......
// Implements VSyncSource::Callback
void onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) override;
}
1.6 总结
这部分的主线就是整理 app 是如何向 VsyncDispatch 注册回调的,过程中涉及到各个类的创建。
1.6.1 回调的整理
在代码的分析过程中出现了各种"回调",很容易就晕了。 所以要抓住一个主线:VSyncDispatchTimerQueue::timerCallback 是如何回调到 EventThread::onVSyncEvent 的。

1.6.2 调用栈整理
这部分的调用链如下:
arduino
SurfaceFlinger::initScheduler
Scheduler::init -- Scheduler初始化
Scheduler::createVsyncSchedule -- VsyncSchedule 初始化
Scheduler::createConnection -- app appsf 注册回调
Scheduler::makePrimaryDispSyncSource
DispSyncSource::init -- 创建DispSyncSource
CallbackRepeater::init
VSyncCallbackRegistration::VSyncCallbackRegistration -- DispSyncSource::onVsyncCallback 作为回调
VSyncDispatchTimerQueue::registerCallback -- app,appsf 注册到mCallbacks中
VSyncDispatchTimerQueueEntry::init -- 创建对应的Entry
VSyncDispatchTimerQueue.mCallbacks::emplace --添加到mCallbacks
EventThread::init
DispSyncSource::setCallback -- 把EventThread::onVSyncEvent 设置到DispSyncSource下的mCallbacks
最后再补充一下VSyncDispatchTimerQueueEntry和EventThread类图:

2 sf 向VsyncDispatch注册回调
sf 的注册就相对简单了,代码如下: 在 SurfaceFlinger::initScheduler 调用了 "mScheduler->initVsync" 这部分的逻辑代码定义如下:
arduino
Scheduler.h
// 继承impl::MessageQueue
class Scheduler : impl::MessageQueue {
// 定义别名
using Impl = impl::MessageQueue;
......
using Impl::initVsync;
......
}
所以真正执行的是 MessageQueue::initVsync 方法。
php
# native\services\surfaceflinger\Scheduler\MessageQueue.cpp
void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
frametimeline::TokenManager& tokenManager,
std::chrono::nanoseconds workDuration) {
setDuration(workDuration);
mVsync.tokenManager = &tokenManager;
// 创建VSyncCallbackRegistration,名字是 sf
mVsync.registration = std::make_unique<
scheduler::VSyncCallbackRegistration>(dispatch,
std::bind(&MessageQueue::vsyncCallback, this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3),
"sf");
......
}
这里构建了一个 VSyncCallbackRegistration 对象,传递了 MessageQueue::vsyncCallback 作为回调,这个回调也是最终 sf 收到的回调
相对于 app 的注册,直接就创建 VSyncCallbackRegistration 对象,并没有 DispSyncSource 和 CallbackRepeater 的创建。
而后面的代码就和 app 的注册逻辑一样了。
css
# VSyncDispatchTimerQueue.cpp
VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,
VSyncDispatch::Callback callback,
std::string callbackName)
: mDispatch(dispatch),
mToken(dispatch.registerCallback(std::move(callback), std::move(callbackName))),
mValidToken(true) {}
可以看到到了这里又是调用了 VSyncDispatchTimerQueue::registerCallback 方法,和 app ,appsf 注册监听是一样的。
c
# VSyncDispatchTimerQueue.cpp
VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Callback callback, std::string callbackName) {
std::lock_guard lock(mMutex);
return CallbackToken{
mCallbacks
.emplace(++mCallbackToken,
std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
std::move(callback),
mMinVsyncDistance))
.first->first};
}
-
- 构建出一个 VSyncDispatchTimerQueueEntry 对象
-
- 将其放到了 mCallbacks 中
sf 的回调逻辑就简单很多

2.1 Trace :Vsync-sf 的输出
void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) { ATRACE_CALL(); // Trace VSYNC-sf Trace处理 mVsync.value = (mVsync.value + 1) % 2; { std::lock_guard lock(mVsync.mutex); mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime); mVsync.scheduledFrameTime.reset(); }
scss
const auto vsyncId = mVsync.tokenManager->generateTokenForPredictions(
{targetWakeupTime, readyTime, vsyncTime});
// SurfaceFlinger 后续处理
mHandler->dispatchFrame(vsyncId, vsyncTime);
}
Trace 上 VSYNC-sf 有波动,然后 SurfaceFlinger 就开始做合成工作。
3 总结
本篇介绍了 app 和sf 向 VsyncDispatch 注册回调的过程,这部分的代码有点绕,特别是涉及到了多个类的关系和多个回调。 这部分的代码可以不用很清楚,个人觉得知道以下三点就好:
-
- 定时结束触发的是 VSyncDispatchTimerQueue::timerCallback
-
- app 接收 Vsync-app 的方法是 DispSyncSource::onVsyncCallback
-
- sf 接收 Vsync-sf 的方法是 MessageQueue::vsyncCallback
其他的逻辑相对来说就没那么重要了,有个印象即可,必要时在当前文章能走到对应的代码逻辑就好。
下面对本篇的内容做个小结。 注册是在开机过程中初始化 SurfaceFlinger 触发 SurfaceFlinger::initScheduler 方法开始的。 调用链如下:
arduino
SurfaceFlinger::initScheduler
Scheduler::init -- Scheduler初始化
Scheduler::createVsyncSchedule -- VsyncSchedule 初始化
VsyncSchedule::emplace
VsyncSchedule::init
VsyncSchedule::createTracker -- VsyncTracker
VsyncSchedule::createDispatch -- VsyncDispatch(节拍器)
Timer::Timer -- 定时器创建
VSyncDispatchTimerQueue::init
VsyncSchedule::createController -- VsyncController
Scheduler::createConnection -- app appsf 注册回调
Scheduler::makePrimaryDispSyncSource
DispSyncSource::init -- 创建DispSyncSource传入VSyncDispatch
CallbackRepeater::init
VSyncCallbackRegistration::VSyncCallbackRegistration -- DispSyncSource::onVsyncCallback 作为回调
VSyncDispatchTimerQueue::registerCallback -- app,appsf 注册到mCallbacks中
VSyncDispatchTimerQueueEntry::init
VSyncDispatchTimerQueue.mCallbacks::emplace --添加到mCallbacks
EventThread::init
DispSyncSource::setCallback -- 把 EventThread::onVSyncEvent 设置到DispSyncSource下的mCallbacks
MessageQueue::initVsync -- sf 注册回调
VSyncCallbackRegistration::VSyncCallbackRegistration
VSyncDispatchTimerQueue::registerCallback -- 注册到mCallbacks中
VSyncDispatchTimerQueueEntry::init
VSyncDispatchTimerQueue.mCallbacks::emplace
-
- 都是在 SurfaceFlinger::initScheduler 开始触发的
-
- Scheduler 创建后会创建 VsyncSchedule ,这个类会触发3个关键类的创建,特别是节拍器 VsyncDispatch
-
- 产生 SW-Vsync 的地方是在 VsyncDispatch ,定时结束后执行 VSyncDispatchTimerQueue::timerCallback
-
- app appsf sf 都会创建一个 VSyncDispatchTimerQueueEntry 对象,然后注册到 VSyncDispatchTimerQueue 下的 mCallbacks 中
-
- app appsf 的注册相对复杂,以 DispSyncSource 为桥梁,然后在创建 VSyncCallbackRegistration 完成后续的注册
-
- sf 的注册相对简单一些,直接创建 VSyncCallbackRegistration 完成后续的注册
-
- app appsf 注册的回调函数是 DispSyncSource::onVsyncCallback ,且最终会调用到 EventThread::onVSyncEvent
-
- sf 注册是回调函数是 MessageQueue::vsyncCallback

当 VsyncDispatch(节拍器)产生 Vsync 的时候就会触发子类 VSyncDispatchTimerQueue 下的 mCallbacks 遍历,把 VSync 时间传递给集合下的每个元素。 目前已知的是这个 mCallbacks 下面有三个元素 app appsf sf。前面两个为线程,sf 为 MessageQueue 类型。
app,appsf,sf注册回调流程图如下:

相同点就是都会通过 VSyncCallbackRegistration 完成注册,并且构建对应的 VSyncDispatchTimerQueueEntry 对象再添加到 VSyncDispatchTimerQueue 下的 mCallbacks 中。
参考:
<千里马学框架-SurfaceFlinger>