[Android禅修之路] 解读Vsync(一)
一 概述
说到 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<EventThreadConnection> eventConnection,
std::unique_ptr<EventThread> eventThread)
: handle(handle), eventConnection(eventConnection), thread(std::move(eventThread)) {}
~Connection() = default;
sp<ConnectionHandle> handle;
sp<EventThreadConnection> eventConnection;
const std::unique_ptr<EventThread> thread;
};
接下来再看看这个 EventThread 是创建的具体过程以及它里面的消息处理逻辑。
1.3 Scheduler::makeEventThread
首先看到这个 EventThread 是通过 makeEventThread 创建的,这个函数是调度器 Scheduler 中的一个函数,之前已经说了,这个调度器 Scheduler 中有一个 DispSync 对象 , 这里又通过这个 DispSync 对象创建了一个 DispSyncSource 对象,然后又通过 DispSyncSource 创建了一个管理 Vsync 的 EventThread。
// 创建 EventThread,这个 EventThread 就是管理 Vsync 的
std::unique_ptr<EventThread> Scheduler::makeEventThread(
const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
nsecs_t offsetThresholdForNextVsync,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
// 首先通过 dispSync 创建一个DispSyncSource
std::unique_ptr<VSyncSource> eventThreadSource =
std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, offsetThresholdForNextVsync,
true, connectionName);
// 创建一个EventThread,传入的参数有三个,分别是
// DispSyncSource
// interceptCallback 和 线程名
return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
std::move(interceptCallback), connectionName);
}
关于 DispSync 的详细介绍在第四节[四 DispSync],下面先詳細描述一下整個初始化的流程。
二 EventThread
在调度器 Scheduler 中创建的 EventThread 就是负责处理 Vsync 信号分发的线程,这个 EventThread 的创建只做了两件事
- 设置 VSyncSource 的回调 , 这个 VSyncSource 其实就是 DispSync,它就是 Vsync 的信号源,而它设置的回调就是自己 this。
- 创建一个线程,这个线程调用了 threadMain 函数 , 这个 threadMain 是 EventThread 的核心函数。EventThread 它不是一个线程,它里面创建的 mThread 才是真正的工作线程。
2.1 EventThread::EventThread
[frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
// EventThread的构造函数
EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
: mVSyncSource(src),
mVSyncSourceUnique(std::move(uniqueSrc)),
mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
mThreadName(threadName) {
if (src == nullptr) {
mVSyncSource = mVSyncSourceUnique.get();
}
//给 VSync 设置回调,回调对象就是自己 this
mVSyncSource->setCallback(this);
//创建一个线程,线程调用 threadMain 函数
mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
threadMain(lock);
});
...
}
注意: 这里传入了之前创建的 DispSyncSource , 然后调用了一个mVSyncSource->setCallback
, 虽然这个函数很简单,但是它比较重要
[frameworks/native/services/surfaceflinger/Scheduler/DispSyncSource.cpp]
void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
std::lock_guard lock(mCallbackMutex);
mCallback = callback;
}
这个函数就是设定了一个 mCallback,也就是说这个 Vsync 信号源的回调就是这个 EventThread 了。
再根据之前 SurfaceFlinger 的初始化中创建传入的回调函数,就可以大致猜出 Vsync 信号的传递过程如下
- Vsync 发出信号,EventThread 的回调函数被调用
- EventThread 的回调函数调用到连接器 EventThreadConnection 中
- 最后通过连接器调用到一开始传入的回调函数。
2.2 EventThread::threadMain
之前已经说了这个 threadMain 就是负责分发 Vsync 信号的线程,下面就来具体看看它是如何分发 Vsync 信号的
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
// 关于 DisplayEventConsumers,它是一个 EventThreadConnection 的集合
// using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;
DisplayEventConsumers consumers;
//退出之前,死循环
while (mState != State::Quit) {
std::optional<DisplayEventReceiver::Event> event;
// DisplayEventReceiver::Event 的队列
if (!mPendingEvents.empty()) {
// 取出队列头元素
event = mPendingEvents.front();
mPendingEvents.pop_front();
// 这里有两种 Event,分别是热拔插和 VSYNC
switch (event->header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
...
break;
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
//调用VSYNC的回调
if (mInterceptVSyncsCallback) {
mInterceptVSyncsCallback(event->header.timestamp);
}
break;
}
}
//是否有 VSYNC 请求
bool vsyncRequested = false;
// mDisplayEventConnections 是一个 EventThreadConnection 的集合
// 而 EventThreadConnection 是 SurfaceFlinger 和 EventThread 的连接
// 这里是取出一个 EventThreadConnection
auto it = mDisplayEventConnections.begin();
while (it != mDisplayEventConnections.end()) {
// 弱指针升级强指针
if (const auto connection = it->promote()) {
//如果 connection 不为 None,则 vsyncRequested 为 true
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
//只要 connection->vsyncRequest 不为None,shouldConsumeEvent 就会返回 true
if (event && shouldConsumeEvent(*event, connection)) {
// 如果消费者请求 Vsync 事件,就讲它将添加到消费者集合 connection
consumers.push_back(connection);
}
++it;
} else {
it = mDisplayEventConnections.erase(it);
}
}
//如果消费者不为空,则分发事件给消费者
if (!consumers.empty()) {
dispatchEvent(*event, consumers);
consumers.clear();
}
//判断是否有 VSYNC 请求
State nextState;
if (mVSyncState && vsyncRequested) {
//判断VSYNC类型SyntheticVSync和VSync
//mVSyncState->synthetic在息屏时为true,亮屏时为false
nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
} else {
//没有VSYNC
nextState = State::Idle;
}
//VSYNC状态发生了变化
if (mState != nextState) {
if (mState == State::VSync) {
mVSyncSource->setVSyncEnabled(false);
} else if (nextState == State::VSync) {
mVSyncSource->setVSyncEnabled(true);
}
mState = nextState;
}
//还有事件
if (event) {
continue;
}
// 没有事件,状态是Idle,就会陷入等待
if (mState == State::Idle) {
mCondition.wait(lock);
} else {
// 没有事件,状态也不是Idle
const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms;
if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
// 那么就伪造一个 Vsync 信号进行分发,下次就会再重新判断是否进入等待
mPendingEvents.push_back(makeVSync(mVSyncState->displayId,
systemTime(SYSTEM_TIME_MONOTONIC),
++mVSyncState->count));
}
}
}
}
threadMain主要就是处理事件
- 从 mPendingEvents 中取出 Event,如果是 Vsync,则交给回调函数 mInterceptVSyncsCallback 处理(mPendingEvents 是 DisplayEventReceiver::Event 的队列)
- 分发事件 Event 到 DisplayEventConsumers 中(DisplayEventConsumers 是 EventThreadConnection 的集合)
对于EventThread函数,现在有几个疑问
- 既然它是分发事件的,那么事件(mPendingEvents中的Event)是怎么来的
- 这些事件具体是怎么处理的
对于1,我们可以猜到它是通过 Vsync 信号来的。那么 Vsync 信号又是怎么变成 mPendingEvents 中的 Event 的呢。Vsync 信号是一个硬件信号,它是怎么变成系统中的 mPendingEvents 的事件的呢? 对于2,在之前 SF EventThread 创建的时候,已经详细介绍了传递的参数,这个 mInterceptVSyncsCallback 其实就是那里传递进来的参数,通过一层层封装来的,再处理完了 mPendingEvents 中的 Event 之后,又会处理 mDisplayEventConnections 中的 Event,通过调用 dispatchEvent 进行处理。
后续我们会围绕着这两个问题进行研究,首先我们先看这个事件的处理函数 dispatchEvent。
2.3 EventThread::dispatchEvent
dispatchEvent 函数中只调用了一个函数,就是 consumer->postEvent,看来分发事件是通过 postEvent 实现的。
之前已经说过了 DisplayEventConsumers 它是一个 EventThreadConnection 的集合,所以这里其实就是调用的 EventThreadConnection 的 postEvent
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
for (const auto& consumer : consumers) {
switch (consumer->postEvent(event)) {
case NO_ERROR:
break;
case -EAGAIN:
// TODO: Try again if pipe is full.
break;
default:
// Treat EPIPE and other errors as fatal.
removeDisplayEventConnectionLocked(consumer);
}
}
}
2.4 EventThreadConnection::postEvent
在 EventThreadConnection 的 postEvent 中,通过 DisplayEventReceiver 发生了一个事件。
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
这里调用 sendEvents,传递的参数有 event,就是对应的事件。还有一个参数是 mChannel,字面意思就是通道,它是定义在 EventThreadConnection 中的成员变量
class EventThreadConnection : public BnDisplayEventConnection {
gui::BitTube mChannel;
}
BitTube 是 Android 中封装了的 socketpair,它是用于 socket 通信的。也就是说这里通过 socket 通信的方式,将事件从 EventThreadConnection 所在的进程传递到了 mChannel 接收的进程。
2.5 BitTube
接下来简单看一下 BitTube 的定义
2.5.1 构造函数
BitTube::BitTube(size_t bufsize) {
init(bufsize, bufsize);
}
BitTube::BitTube(DefaultSizeType) : BitTube(DEFAULT_SOCKET_BUFFER_SIZE) {}
BitTube::BitTube(const Parcel& data) {
readFromParcel(&data);
}
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
// since we don't use the "return channel", we keep it small...
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
mReceiveFd.reset(sockets[0]);
mSendFd.reset(sockets[1]);
} else {
mReceiveFd.reset();
ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
}
}
BitTube 其实就是一个 socketpair 的封装,socketpair 就是 Android 中使用 socket 进行进程间通信的方式。
2.6 DisplayEventReceiver::sendEvents
ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
Event const* events, size_t count)
{
return gui::BitTube::sendObjects(dataChannel, events, count);
}
2.7 BitTube::sendObjects
ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
const char* vaddr = reinterpret_cast<const char*>(events);
ssize_t size = tube->write(vaddr, count * objSize);
return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
2.8 BitTube::write
ssize_t BitTube::write(void const* vaddr, size_t size) {
ssize_t err, len;
do {
// 调用 socket 的 send 进行进程间的通信
len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
// cannot return less than size, since we're using SOCK_SEQPACKET
err = len < 0 ? errno : 0;
} while (err == EINTR);
return err == 0 ? len : -err;
}
所以 postEvent 最后调用到的是 socket 的 send 函数,使用的就是 socket 通信方式,对应的文件描述符是 mSendFd。
现在我们再来整理一下 BitTube 的调用流程 DisplayEventReceiver::sendEvents -> BitTube::sendObjects -> BitTube::write -> socket::send
最终,就是通过 gui::BitTube 的 sendObjects 将事件传递出去了,在理解了 BitTube 的 socket 的通信方式之后,我们就弄清楚一半了。接下来只需要弄清楚这个 Fd 的监听者是谁,以及它是如何处理事件的。
三 MessageQueue
处理事件是发生在 MessageQueue 中的,我们先从 MessageQueue 的初始化开始。
MessageQueue 是在 SurfaceFlinger 的 init 中初始化的 [见1.1]
MessageQueue 还有一个比较重要的函数 setEventThread。这个函数早期是在 SurfaceFlinger 的 init 函数中直接调用的,但是从 Android 10 开始,它就放在 SurfaceFlinger::enableVSyncInjections 中了,enableVSyncInjections 这个函数,在 SurfaceFlinger 监听到硬件信息后就会调用。
void MessageQueue::setEventThread(android::EventThread* eventThread,
ResyncCallback resyncCallback) {
if (mEventThread == eventThread) {
return;
}
// 这里面的 mEventTube 就是定义在头文件中的 BitTube
if (mEventTube.getFd() >= 0) {
// 先移除当前的 Fd
mLooper->removeFd(mEventTube.getFd());
}
mEventThread = eventThread;
// mEvents 则是 EventThread 对应的 EventThreadConnection,即 EventThread 和 SF 的连接
mEvents = eventThread->createEventConnection(std::move(resyncCallback));
// 通过调用 stealReceiveChannel 函数监听 Vsync 事件对应的 Fd
mEvents->stealReceiveChannel(&mEventTube);
// 然后再添加新的 Fd
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
this);
}
- 这里首先调用了 EventThreadConnection::stealReceiveChannel设置事件 Fd
- 然后调用 Looper::addFd,并将回调函数 MessageQueue::cb_eventReceiver 传递了进去。
其实就是创建一个 epoll 来监听这个 Fd 这个描述符对应的事件,如果收到事件,就会执行 MessageQueue::cb_eventReceiver 的回调函数,之前在 BitTube::write 中发送的事件,最后会在这里收到对应的回调。
所以我们知道,在 EventThread 处理接收到的 Vsync 事件,会通过 socket 通信的方式,回调到 MessageQueue::cb_eventReceiver。
接下来我们看看具体的事件设置过程
3.1 EventThreadConnection::stealReceiveChannel
stealReceiveChannel 中就是设置监听 Vsync 事件 Fd 的过程,参数 outChannel 就是 MessageQueue 中的 mEventTube
frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.h]
// MessageQueue 中 mEventTube 的定义
gui::BitTube mEventTube;
// 定义在 EventThread.h 中
gui::BitTube mChannel;
[frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
outChannel->setReceiveFd(mChannel.moveReceiveFd());
return NO_ERROR;
}
这里的 outChannel 也是一个 BitTube,然后给它添加了 ReceiveFd,也就是 socket 接收事件的监听。这个 Fd 是通过 mChannel 获取的,而 mChannel 是在 EventThreadConnection 创建的时候初始化的,EventThreadConnection 创建发生在 [1.2],通过调用 createConnectionInternal 创建了 EventThreadConnection,并调用了它的构造函数。
[frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
sp<EventThreadConnection> EventThread::createEventConnection(
ResyncCallback resyncCallback,
ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
return new EventThreadConnection(const_cast<EventThread*>(this),
IPCThreadState::self()->getCallingUid(),
std::move(resyncCallback), eventRegistration);
}
EventThreadConnection::EventThreadConnection(
EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback,
ISurfaceComposer::EventRegistrationFlags eventRegistration)
: resyncCallback(std::move(resyncCallback)),
mOwnerUid(callingUid),
mEventRegistration(eventRegistration),
mEventThread(eventThread),
// 初始化 mChannel
mChannel(gui::BitTube::DefaultSize) {}
3.2 MessageQueue::cb_eventReceiver
接下来我们再来看看 MessageQueue 是如何处理 Vsync 事件的。
[frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp]
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
return queue->eventReceiver(fd, events);
}
// 所谓的处理事件,就是将事件通过 mHandler 进行分发,调用到了 dispatchInvalidate 中
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
for (int i = 0; i < n; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
mHandler->dispatchInvalidate();
break;
}
}
}
return 1;
}
MessageQueue 的 cb_eventReceiver,其实会调用到 eventReceiver,在这个里面,有一个对应的 mHandler,来通过 dispatchInvalidate 处理事件。这个 mHandler 就是之前在 SurfaceFlinger 的初始化函数中,通过调用 MessageQueue::init 函数创建的 [见1.1.1]
3.3 dispatchInvalidate
dispatchInvalidate 就是 MessageQueue 内部类 Handler 处理事件的函数。
[frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp]
void MessageQueue::Handler::dispatchInvalidate() {
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
}
}
这里又出现了一个 mQueue,这个 mQueue 就是在 Handler 的构造函数中,传递进来的 this,其实就是 MessageQueue 自己。所以其实就是通过 MessageQueue 的成员变量 mLooper 发送了一条 INVALIDATE 的消息,根据我们对 Handler 机制的了解,消息的处理就需要看 handleMessage 函数了
3.4 handleMessage
在 handleMessage 中,有两种消息的处理,其中一个就是我们之前收到的 INVALIDATE 事件,不过这两种事件都是转交给了 MessageQueue 对应的 SurfaceFlinger,然后通过 SurfaceFlinger 的 onMessageReceived 处理
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
// 这个 mQueue 就是 MessageQueue 自己,mFlinger 就是 SurfaceFlinger
// 这里就会回调到 SurfaceFlinger 的 onMessageReceived
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
到此,Vsync 事件在 SurfaceFlinger 中的传递过程我们基本整理清楚了。那么还有一个问题,就是这个 Vsync 事件是怎么从硬件信号,变成 SurfaceFlinger 的事件的。简单来说,就是这个事件是怎么来的?
之前我们在创建 EventThread 的时候,还传递了一个参数 DispSync,当时的介绍是 Vsync 的事件源,现在就来看看这个事件源是怎么产生 Vsync 事件的。它又是如何将硬件信号变成 SurfaceFlinger 中的事件的