一 概述
说到 Vsync,大家首先想到的肯定是游戏中的垂直同步。可能会有人疑惑,游戏的垂直同步和 Android 的图形系统的关系。其实在 Android 中,同样有着 Vsync 机制。
在 Android 的刷新过程中,Vsync 的作用就是同步的唤醒应用以开始渲染、唤醒 SurfaceFlinger 开始屏幕的合成以及屏幕刷新周期。
在 SurfaceFlinger 渲染的过程中,画面的显示会经过应用程序的绘制,SurfaceFlinger 的合成,以及硬件的显示。这些过程分别处于三个不同的进程中,系统一般采用三缓冲的策略。
也就是当屏幕开始显示第N帧的时候,SurfaceFlinger 会开始为第N+1帧进行合成。而应用则准备的生成第N+2帧。这个具体的流程,就发生在我们之前介绍的 BufferQueue 的生产者和消费者模型中。
Vsync 机制是 SurfaceFlinger 中重要的机制之一,它用于通知在 SurfaceFlinger 的刷新时机。 Vsync 主要的工作过程就是产生 Vsync 信号和分发信号。所以解读 Vsync 机制,就是弄清楚最关键的两个问题:
- Vsync 信号是如何产生的
- Vsync 信号是如何分发到 SurfaceFlinger 的(是如何传递的)
接下来我们就从三个方面一步一步了解 Vsync 机制
- Vsync 的初始化 [节一]
- Vsync 的分发线程的工作原理(部分)[节二]
- Vsync 消息的传递逻辑 [节三]
一 Vsync 的初始化
首先,在 SurfaceFlinger 启动的时候,会做一个初始化的过程,调用 init 函数,在这个函数中,创建一个 EventThread 和一个 MessageQueue,用来处理 Vsync 信号。
[frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::init() {
...
//1 启动 EventThread,EventThread有两个,分别是App EventThread和SF EventThread
// getFactory()拿到的是SurfaceFlingerFactory, 然后创建一个 Scheduler 调度器
mScheduler =getFactory().createScheduler([this](bool enabled) {
setPrimaryVsyncEnabled(enabled);
},mRefreshRateConfigs);
// 通过 mScheduler 创建回调,具体的回调函数是 SurfaceFlinger 的 getVsyncPeriod
auto resyncCallback = mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
// 1.1 App EventThread,传入了创建的回调函数 resyncCallback
mAppConnectionHandle =
mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
resyncCallback,
impl::EventThread::InterceptVSyncsCallback());
// 1.2 SF EventThread,同样传入了刚才创建的回调函数,拿到的是一个 Handle
mSfConnectionHandle = mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
mPhaseOffsets->getOffsetThresholdForNextVsync(),resyncCallback, [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
// 将 Handle(也就是mSfConnectionHandle) 对应的 EventThreadConnection 注入 mEventQueue,这个 mEventQueue 是一个 MessageQueue 消息队列
// 这里很重要
// Handle 对应一个 EventThreadConnection,这个 EventThreadConnection 是一个连接器,它保存着回调函数和Vsync事件源
mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
}
这里的 init 函数,通过 Scheduler 创建了两个 EventThread,一个是 App 的 EventThread ,一个是 SurfaceFlinger 的 EventThread。
因为 Vsync 是通知 SurfaceFlinger 刷新的信号,如果 App 信号和 SF 信号是同步的话,那么就会造成系统工作的拥挤,按照正常的思路,我们应该是希望处理 App 事务和处理 SF 事务是错开的,所以这里用了两个线程来分开处理。并且这两个线程还采用了不同的时间偏移量。
创建完 EventThread 之后,就将 SurfaceFlinger 的 EventConnection 设置进了 EventQueue。
这里出现了几个对象,我们分别来看,首先是 EventQueue。
1.1 MessageQueue
EventQueue 是定义在 SurfaceFlinger 中的一个成员变量,它其实就是一个 MessageQueue ,定义如下
[frameworks/native/services/surfaceflinger/SurfaceFlinger.h]
std::unique_ptr<MessageQueue> mEventQueue;
MessageQueue 是 Android 中比较常见的一个机制,这里的 mEventQueue 会在创建 SurfaceFlinger 的强指针的时候初始化。
[frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::onFirstRef() {
mEventQueue->init(this);
}
1.1.1 MessageQueue::init
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
初始化就是创建对应的 Looper 和 Handler。Handler 是 MessageQueue 的内部类
1.1.2 MessageQueue::Handler
class MessageQueue final : public android::MessageQueue {
class Handler : public MessageHandler {
...
这里就是 Android 中经常用的 Handler 和 MessageQueue 机制
接下来再看 EventConnection 这个对象,它是通过 Scheduler::createConnection 创建的
1.2 Scheduler::createConnection
createConnection 其实就是建立连接,它会创建一个 EventThread 对象,并将它与 SurfaceFlinger 建立相应的关联。这里传递进来的参数很多
- connectionName:连接名,传入的分别是 app 和 sf,也就是 app 和 sf 都会建立连接
- phaseOffsetNs:相位差,传入的分别是 mVsyncModulator.getOffsets().app和 mVsyncModulator.getOffsets().sf。之前已经说过了,我们希望系统在分发 App 信号和 SF 信号时是错开的,这样就能避免系统工作的拥挤,这个错开的方式就是通过相位差实现的
- offsetThresholdForNextVsync:下个Vsync的偏移阈值,传入的是mPhaseOffsets->getOffsetThresholdForNextVsync(),mPhaseOffsets 在 SurfaceFlinger 创建的时候是0,是在获取硬件信息后重新设置的值
- resyncCallback:Vsync 信号的回调
- interceptCallback:Vsync 信号拦截的回调
[frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
const char* connectionName,
nsecs_t phaseOffsetNs,
nsecs_t offsetThresholdForNextVsync,
ResyncCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
// 创建一个管理 Vsync 的 EventThread
// mPrimaryDispSync.get()是一个 DispSync,这个 DispSync 是合成延时的 Vsync 源
// 关于 DispSync 的介绍见[四 DispSync]
// 然后通过这个 Vsync 源创建一个 EventThread 关联,这样这个 EventThread 就可以产生 Vsync 信号的通知事件了
std::unique_ptr<EventThread> eventThread =
makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
offsetThresholdForNextVsync, std::move(interceptCallback));
// 创建 EventThread 的 Connection 连接 EventThreadConnection
auto eventThreadConnection =
createConnectionInternal(eventThread.get(), std::move(resyncCallback),
ISurfaceComposer::eConfigChangedSuppress);
// mConnections是一个Connection的集合
// 将创建的 EventThreadConnection 保存到这个 Connection 的集合中
mConnections.emplace(id,
std::make_unique<Connection>(new ConnectionHandle(id),
eventThreadConnection,
std::move(eventThread)));
// Connection 的 handle 是一个 BBinder
return mConnections[id]->handle;
}
Scheduler 中有一个 DispSync,这个 DispSync 是在 Scheduler 的构造函数中创建的,它其实就是 Vsync 的信号源,mPrimaryDispSync.get()拿到的就是 DispSync
通过 makeEventThread 创建完 EventThread 之后,会将 EventThread和 SF 的 Vsync 回调进行绑定,创建出一个 EventThreadConnection,这样这个 EventThreadConnection 就既有 Vsync 事件的信号源,又有对应的回调。 然后就将这个 EventThreadConnection 保存到一个名为 mConnections 的 Connection 集合,这个 Connection 其实就是 Scheduler 的内部类,它包含三个成员变量,分别是
- ConnectionHandle 指针,它是 BBinder 的子类
- EventThreadConnection 指针,这个 EventThreadConnection 它有包含 EventThread 和对应的 SF 回调
- EventThread 指针
class Connection {
public:
Connection(sp<ConnectionHandle> handle, sp<EventThreadConnec