1 垂直同步信号
VSync(即V-Sync垂直同步)的具体含义和用途文章不细说,看下图的VSync的位置大致也就知道它的用途(简单理解成是硬件定时中断貌似也可以,周期性的硬件中断,频率为60Hz,周期为0.0167s,也就是16ms)。
本文主要关注以下几个问题:
(1)VSync是如何产生的?
(2)VSync最初是在哪个进程中捕获的?
(3)VSync是如何分发到各个应用进程的?
(4)view.invalidate是如何与VSync配合,从而实现重绘的?
2 SurfaceFlinger进程
以前的Android系统中SurfaceFlinger是在System_Server进程中的,但是自从Android4.x(x具体是几,没细查)开始SurfaceFlinger已经开始作为一个独立的进程存在,具体的进程入口在Main_surfaceflinger.cpp文件的main函数中,简单看一下这个函数:
int main(int, char**) {
signal(SIGPIPE, SIG_IGN);
// When SF is launched in its own process, limit the number of
// binder threads to 4. 设置线程池最多只能有4个Binder线程
ProcessState::self()->setThreadPoolMaxThreadCount(4);
//创建进程的ProcessState对象,打开binder设备,同时创建并映射一部分Binder共享内存
sp<ProcessState> ps(ProcessState::self());
//开启Binder线程,里面会有循环不断的talkWithDriver
ps->startThreadPool();
// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); //设置surfaceflinger进程的优先级
set_sched_policy(0, SP_FOREGROUND);
// initialize before clients can connect
flinger->init(); //初始化 SurfaceFlinger 对象
// publish surface flinger
//返回的sm是一个BpServiceManager对象,相当于是new BpServiceManager(new BpBinder(0))
sp<IServiceManager> sm(defaultServiceManager());
//BpServiceManager向service_manager守护进程注册当前的SurfaceFlinger服务,里面传进来了SurfaceFlinger对象flinger
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
// run in this thread
flinger->run();
return 0;
}
相关的注释上面都有,SurfaceFlinger作为核心服务还是很复杂的,里面涉及到的东西太多了。看一下SurfaceFlinger.init函数(SurfaceFlinger.cpp):
与垂直同步信号相关的关键代码是截图中的最后一行:
mHwc = new HWComposer(this,*static_cast<HWComposer::EventHandler *>(this));
里面给的两个参数其实都是指向SurfaceFlinger对象本身,记住这一点,继续往下。
2.1 分析HWComposer
代码在HWComposer.h HWComposer.cpp中,分析C++代码和Java代码有一点很大的区别,同样是类的成员变量,C++成员变量很多都是实际的对象(至于是栈对象还是堆对象,要看外部对象是直接创建的栈对象,还是new创建的堆对象),而Java代码里面的成员一定要在new对象以后才有实际的实体,看一下HWComposer的成员变量:
sp<SurfaceFlinger> mFlinger; //指针
framebuffer_device_t* mFbDev; //指针
structhwc_composer_device_1* mHwc; //指针
structhwc_display_contents_1* mLists[MAX_HWC_DISPLAYS]; //指针数组
DisplayData mDisplayData[MAX_HWC_DISPLAYS]; //DisplayData对象数组
mutable Mutex mDisplayLock; //锁对象
size_t mNumDisplays;
cb_context* mCBContext; //指针
EventHandler& mEventHandler; //引用
size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
sp<VSyncThread> mVSyncThread; //指针
bool mDebugForceFakeVSync;
BitSet32 mAllocatedDisplayIDs; //对象
mutable Mutex mLock; //锁对象
mutable nsecs_t mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
mutable Mutex mEventControlLock; //锁对象
上面这一点在分析C++代码的时候要尤其注意,看一下HWComposer的构造函数:
HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger, EventHandler& handler)
: mFlinger(flinger),
mFbDev(0), mHwc(0), mNumDisplays(1), //初始情况下mHwc是一个空指针
mCBContext(new cb_context), //这里新创建了一个cb_context对象
mEventHandler(handler),
mDebugForceFakeVSync(false)
{
bool needVSyncThread = true;
.....
// Note: some devices may insist that the FB HAL be opened before HWC. 尝试打开硬件HWC
int fberr = loadFbHalModule();
loadHwcModule(); //加载HWC模块,若打开成功,则mHwc将不为空
.......
if (mHwc) {
ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
(hwcApiVersion(mHwc) >> 24) & 0xff,
(hwcApiVersion(mHwc) >> 16) & 0xff);
if (mHwc->registerProcs) {
mCBContext->hwc = this;
mCBContext->procs.invalidate = &hook_invalidate;
mCBContext->procs.vsync = &hook_vsync; //硬件产生中断,通过hook_vsync函数进行同步信号的通知
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
mCBContext->procs.hotplug = &hook_hotplug;
else
mCBContext->procs.hotplug = NULL;
memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
mHwc->registerProcs(mHwc, &mCBContext->procs);
}
// don't need a vsync thread if we have a hardware composer 存在硬件同步信号发生器,就不需要软件模拟线程
needVSyncThread = false;
}
............
if (needVSyncThread) { //设备不支持硬件HWC,用软件模拟同步信号,这里不讨论,整个的流程还是一样的
// we don't have VSYNC support, we need to fake it
mVSyncThread = new VSyncThread(*this);
}
}
上面的代码首先执行参数初始化表,根据前面的记录,这里的mFlinger和mEventHandler指向的都是前面的SurfaceFlinger对象, 然后加载HWC模块,实际上对应的是一个so库,读取到里面的相关信息后,设置了里面的产生硬件同步信号时候的回调函数是hook_vsync,这里就是将产生硬件同步信号时相应的函数入口存储到HWC模块的相关结构中,看一下hook_vsync函数的声明和定义:
声明:
static void hook_invalidate(conststructhwc_procs* procs);
static void hook_vsync(conststructhwc_procs* procs, int disp,int64_t timestamp);
static void hook_hotplug(conststructhwc_procs* procs, int disp, int connected);
只有static类型的函数可以作为回调函数将函数名称作为参数直接传递,这是因为static函数不需要依赖对象的this指针,相应的函数地址在编译期间即可确定。
定义:
void HWComposer::hook_vsync(conststruct hwc_procs* procs, int disp, int64_t timestamp) {
cb_context* ctx = reinterpret_cast<cb_context*>(const_cast<hwc_procs_t*>(procs));
ctx->hwc->vsync(disp, timestamp);
}
注意看上面HWComposer构造器中被标红的几行,里面的ctx->hwc指向的就是当前的this指针,也就是当前的对象,因此调用的就是当前对象的vsync函数,看一下这个函数:
void HWComposer::vsync(int disp, int64_t timestamp) {
if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
{
Mutex::Autolock _l(mLock);
// There have been reports of HWCs that signal several vsync events
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
// out here so they don't cause havoc downstream.
mLastHwVSync[disp] = timestamp; //记录编号为disp的显示设备的sync时间
}
char tag[16];
snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
//HWC以及VSyncThread软件模拟,最终都是通过mEventHandler.onVSyncReceived函数将同步信号发出去的
mEventHandler.onVSyncReceived(disp, timestamp);
}
}
最重要的就是调用了mEventHandler.onVSyncReceived()函数,前面分析到,这里mEventHandler实际上就是创建当前HWComposer对象的SurfaceFlinger对象,因此会调用SurfaceFlinger.onVSyncReceived()函数,经过上面的一启动过程,HWC硬件产生的同步信号就可以到达SurfaceFlinger里面了。
2.2 SurfaceFlinger分发vsync
先看一下mPrimaryHWVsyncEnabled这个成员变量,初始情况下是false,实际经过下面的调用后会变成true:
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
bool needsHwVsync = false;
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
if (type == 0 && mPrimaryHWVsyncEnabled) {
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}
if (needsHwVsync) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
}
这里的type实际上就是DisplayDevice的类型,上面的设置的时候就是DisplayDevice::DISPLAY_PRIMARY,这个值就是0,上面分析mPrimaryHWVsyncEnabled是true,因此会调用到mPrimaryDispSync.addResyncSample函数,至于下面的if判断就没有必要看了,里面enableHardwareVsync的时候若mPrimaryHWVsyncEnabled=true就直接返回了,看一下变量和mPrimaryDispSync.addResyncSample函数:
这里mPrimaryDispSync是一个DispSync对象,看一下构造函数:
DispSync::DispSync() : mRefreshSkipCount(0), mThread(new DispSyncThread()) {
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
reset();
beginResync(); .....
}
这里面最重要的就是创建了一个DispSyncThread线程,然后立马运行,根据C++层的线程模型,线程对象一旦运行后,会反复调用线程对象的threadLoop函数,因此这个线程一直运行DispSyncThread.threadLoop函数:
virtual bool threadLoop() {
while (true) {
Vector<CallbackInvocation> callbackInvocations;
nsecs_t targetTime = 0;
{ // Scope for lock
Mutex::Autolock lock(mMutex);
bool isWakeup = false;
if (now < targetTime) {
err = mCond.waitRelative(mMutex, targetTime - now);
}
now = systemTime(SYSTEM_TIME_MONOTONIC);
callbackInvocations = gatherCallbackInvocationsLocked(now);
}
if (callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations);
}
}
returnfalse;
}
继续看上面的DispSync.addResyncSample函数:
里面的主要函数调用如下:
DispSync.addResyncSample—–>DispSync.DispSyncThread.updateModel,看一下updateModel函数,里面主要唤醒了在mCond变量上被阻塞的线程:
DispSyncThread.threadLoop函数然后执行gatherCallbackInvocationsLocked,从mEventListeners中收集所有满足时间条件的EventListener,然后在fireCallbackInvocations中调用:
void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
可见fireCallbackInvocations函数调用了各个监听器的onDispSyncEvent函数。
经过上述分析可知,SurfaceFlinger接收到HWC的垂直同步信号后,调用SurfaceFlinger.onVSyncReceived()将VSync分发给了SurfaceFlinger.mPrimaryDispSync,SurfaceFlinger.mPrimaryDispSync调用了mEventListeners中所有满足条件的listener,下面就看这些listener是如何注册到SurfaceFlinger.mPrimaryDispSync.mEventListeners里面的。
2.3 DispSyncSource
上面讲到是分发给了SurfaceFlinger.mPrimaryDispSync,继续看一下SurfaceFlinger.init函数:
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc);
mEventQueue.setEventThread(mSFEventThread);
里面创建了两个EventThread对象,并且创建的时候给的参数是一个包装了上述mPrimaryDispSync的DispSyncSource对象,简单看一下DispSyncSource里面的函数,里面有戏,这里先不分析DispSyncSource,先分析EventThread和mEventQueue相关的内容,根据前面的经验,一般Thread类主要看3个方法:构造器、onFirstRef以及threadLoop方法,对应各自的主要功能如下:
(1)EventThread的构造器:设置mVSyncEvent[type]中各个变量属性,后面分析threadLoop相关方法的时候需要参照;
(2)onFirstRef:为什么需要分析这个方法呢?这个方法纯粹是sp指针会用到,一时给忘了暂时先略过,可以认为构造器运行结束这个方法就会执行,这个函数调用了EventThread.run;
(3)threadLoop:线程循环
// This will return when 注释说:当线程开始等待时,这个函数在获取到vsync同步事件并且至少有一个连接对该同步信号感兴趣的时候才会返回
//(1) a vsync event has been received, and
//(2) there was at least one connection interested in receiving it when we started waiting.
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(DisplayEventReceiver::Event* event){
Mutex::Autolock _l(mLock);
Vector< sp<EventThread::Connection> > signalConnections;
do {
bool eventPending = false;
bool waitForVSync = false;
size_t vsyncCount = 0;
nsecs_t timestamp = 0;
//初始情况下下面的for循环结束后timestamp还是0
for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
timestamp = mVSyncEvent[i].header.timestamp; //参照EventThread的构造器,初始为0
if (timestamp) {
// we have a vsync event to dispatch
*event = mVSyncEvent[i]; //注意这里将mVSyncEvent[i]复制完后,就将里面的timestamp重新设置成0
mVSyncEvent[i].header.timestamp = 0;
vsyncCount = mVSyncEvent[i].vsync.count;
break;
}
}
//初始情况下下面的for循环结束后timestamp还是0,这里的mPendingEvents也是空的
if (!timestamp) {
// no vsync event, see if there are some other event
eventPending = !mPendingEvents.isEmpty();
if (eventPending) {
// we have some other event to dispatch
*event = mPendingEvents[0];
mPendingEvents.removeAt(0);
}
}
// find out connections waiting for events 初始情况下下面的for循环结束后timestamp还是0,这里的mPendingEvents也是空的,下面的mDisplayEventConnections也是空的
size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
sp<Connection> connection(mDisplayEventConnections[i].promote());
........//后面再列出
}
.......
// note: !timestamp implies signalConnections.isEmpty(), because we
// don't populate signalConnections if there's no vsync pending
if (!timestamp && !eventPending) {
// wait for something to happen
if (waitForVSync) {
......
}
} else {
//如果当前EventThread线程没有任何Connection连接,这里会进入休眠状态,不再接收同步信号,注意看EventThread::Connection::onFirstRef(),
//该函数里面会调用EventThread::registerDisplayEventConnection,也就是一旦新建了Connection连接,立马会调用mCondition.broadcast()尝试
//唤醒处于休眠状态的EventThread线程,开始监听同步信号,并在下次接收到同步信号后转发给Connection连接的对象
// Nobody is interested in vsync, so we just want to sleep.
// h/w vsync should be disabled, so this will wait until we
// get a new connection, or an existing connection becomes
// interested in receiving vsync again.
mCondition.wait(mLock); //初始情况下,直接到这里被挂起了
}
}
} while (signalConnections.isEmpty());
// here we're guaranteed to have a timestamp and some connections to signal
// (The connections might have dropped out of mDisplayEventConnections
// while we were asleep, but we'll still have strong references to them.)
return signalConnections;
}
初始情况下,进入到了mCondition.wait(mLock);的状态下,直接被挂起了,这时候假设mCondition被解锁,要想结束当前的do{…}while;循环,signalConnections必须不为空,也就是mDisplayEventConnections必须有连接在里面,SF创建完EventThread保存在mSFEventThread里面,继续看SurfaceFlinger.init函数里面的mEventQueue.setEventThread(mSFEventThread):
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEventTube = mEvents->getDataChannel();
mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver, this);
}
里面首先调用上面mSFEventThread线程的createEventConnection方法:
sp<EventThread::Connection> EventThread::createEventConnection() const {
returnnew Connection(const_cast<EventThread*>(this));
}
这里创建了一个EventThread::Connection对象,看一下:
classEventThread : public Thread, privateVSyncSource::Callback {
classConnection : public BnDisplayEventConnection { //这个Connection还是一个Binder机制的服务端,对应BnDisplayEventConnection
public:
Connection(const sp<EventThread>& eventThread);
status_t postEvent(const DisplayEventReceiver::Event& event);
// count >= 1 : continuous event. count is the vsync rate
// count == 0 : one-shot event that has not fired
// count ==-1 : one-shot event that fired this round / disabled
int32_t count;
private:
virtual~Connection();
virtualvoidonFirstRef();
virtual sp<BitTube> getDataChannel() const;
virtualvoidsetVsyncRate(uint32_t count);
virtualvoidrequestNextVsync(); // asynchronous
sp<EventThread> constmEventThread;
sp<BitTube> constmChannel;
};
}
再看一下构造函数:
EventThread::Connection::Connection(
const sp<EventThread>& eventThread)
: count(-1), mEventThread(eventThread), mChannel(new BitTube()) //初始情况下count=-1 这里的mChannel是一个BitTube对象
{
}
void EventThread::Connection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
//向当前线程注册自己这个连接,会将新的连接添加到mDisplayEventConnections里面
mEventThread->registerDisplayEventConnection(this);
}
先看这个onFirstRef函数,里面调用到了前面传件来的mSFEventThread对象的registerDisplayEventConnection方法,看一下:
status_t EventThread::registerDisplayEventConnection(const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
mDisplayEventConnections.add(connection);
mCondition.broadcast();
return NO_ERROR;
}
上面的注释写的很清楚:
count>=1: 持续的接收事件,count代表接收垂直同步信号的频率,也就是每隔count个垂直同步信号接收一次;
count=0 : 一锤子买卖,只接收一次同步信号;
count=-1: 同样是一锤子买卖,但是已经被处理了,初始的默认值;
这里将刚才创建的EventThread::Connection对象加到了mSFEventThread.mDisplayEventConnections里面,再看EventThread::waitForEvent:
size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
sp<Connection> connection(mDisplayEventConnections[i].promote());
if (connection != NULL) {
bool added = false;
if (connection->count >= 0) { // >=0 代表当前的Connection需要接收同步信号
waitForVSync = true;
if (timestamp) { // timestamp 初始情况是0,也就是初始情况是不会加到signalConnections里面的
if (connection->count == 0) {
// fired this time around
connection->count = -1;
signalConnections.add(connection);
added = true;
} else if (connection->count == 1 ||
(vsyncCount % connection->count) == 0) {
// continuous event, and time to report it
signalConnections.add(connection);
added = true;
}
}
}
if (eventPending && !timestamp && !added) {
signalConnections.add(connection);
}
} else {
// we couldn't promote this reference, the connection has
// died, so clean-up!
mDisplayEventConnections.removeAt(i);
--i; --count;
}
}
//注意看这里的注释,下面这个判断主要是用于使能或者是停止同步信号的分发
// Here we figure out if we need to enable or disable vsyncs
if (timestamp && !waitForVSync) {
// we received a VSYNC but we have no clients
// don't report it, and disable VSYNC events
//接收到了同步信号,但是该线程目前没有任何的客户端,所以不需要进行分发信号,同时停止监听同步信号
disableVSyncLocked();
} else if (!timestamp && waitForVSync) { //初始情况创建完Connection调用registerDisplayEventConnection注册以后,会走到这里
enableVSyncLocked();
}
看一下enableVSyncLocked这个函数:
void EventThread::enableVSyncLocked() {
//这里的mVSyncSource实际上是一个DispSyncSource对象,调用SF.DispSyncSource.setVSyncEnabled(true)会调用DispSync.addEventListener将
//当前EventThread注册的同步信号的监听器添加到DispSync
if (!mUseSoftwareVSync) { //这里用的是硬件垂直信号
// never enable h/w VSYNC when screen is off
if (!mVsyncEnabled) {
mVsyncEnabled = true;
mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
mVSyncSource->setVSyncEnabled(true);
}
}
mDebugVsyncEnabled = true;
sendVsyncHintOnLocked();
}
这里的mVSyncSource是SurfaceFlinger::DispSyncSource,因此接下来调用的是SurfaceFlinger::DispSyncSource.setCallback和setVSyncEnabled函数:
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->addEventListener(mPhaseOffset, static_cast<DispSync::Callback*>(this));
} else {
status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));
}
mEnabled = enable;
}
virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
Mutex::Autolock lock(mCallbackMutex);
= callback;
}
先将EventThread对象的this指针转换为基类VSyncSource::Callback指针,对应的是onVSyncEvent函数,也就是这里的SurfaceFlinger::DispSyncSource.mCallback可以直接认为对应的是EventThread.onVSyncEvent函数,再看一下setVSyncEnabled函数,调用了DispSync.addEventListener函数:
status_t DispSync::addEventListener(nsecs_t phase,
const sp<Callback>& callback) {
Mutex::Autolock lock(mMutex);
return mThread->addEventListener(phase, callback);
}
下面调用到DispSync::DispSyncThread.addEventListener函数:
status_t addEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < mEventListeners.size(); i++) {
if (mEventListeners[i].mCallback == callback) {
return BAD_VALUE;
}
}
EventListener listener;
listener.mPhase = phase;
listener.mCallback = callback;
listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC) - mPeriod / 2;
mEventListeners.push(listener);
mCond.signal();
return NO_ERROR;
}
根据前面的分析可以知道:
HWComposer(产生VSync)--->SurfaceFlinger.onVSyncReceived
--->DispSync.updateModelLocked-->DispSyncThread.updateModel
--->回调所有注册的监听器的onDispSyncEvent函数
现在信号的传递就变成mEventListeners.mCallback.onDispSyncEvent(这里调用的是SurfaceFlinger.DispSyncSource.onDispSyncEvent函数),看一下这个函数:
virtual void onDispSyncEvent(nsecs_t when) {
sp<VSyncSource::Callback> callback;
{
Mutex::Autolock lock(mCallbackMutex);
callback = mCallback;
}
if (callback != NULL) {
callback->onVSyncEvent(when);
}
}
很显然直接调用了SurfaceFlinger.DispSyncSource.mCallback回调函数,根据上面的分析可知,这个会调用到EventThread.onVSyncEvent函数:
void EventThread::onVSyncEvent(nsecs_t timestamp) {
Mutex::Autolock _l(mLock);
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = 0;
mVSyncEvent[0].header.timestamp = timestamp;
mVSyncEvent[0].vsync.count++;
mCondition.broadcast();
}
里面主要是会调用到mCondition.broadcast()唤醒正在waitForEvent的EventThread线程,最终会继续执行EventThread的threadLoop函数:
bool EventThread::threadLoop() {
DisplayEventReceiver::Event event;
Vector< sp<EventThread::Connection> > signalConnections;
//在这里会被阻塞,然后在onVSyncEvent函数中的mCondition.broadcast()中被唤醒
signalConnections = waitForEvent(&event);
// dispatch events to listeners...
const size_t count = signalConnections.size();
for (size_t i=0 ; i<count ; i++) {
const sp<Connection>& conn(signalConnections[i]);
status_t err = conn->postEvent(event);
}
return true;
}
接下来最主要的是调用了connnection->postEvent,这个函数经过一下步骤:
(1)DisplayEventReceiver::sendEvents
(2)BitTube::sendObjects
(3)BitTube::write
最终调用到了BitTube::write函数,其中当前的BitTube对象就是在创建EventThread::Connection时创建的,看一下BitTube::write函数
ssize_t BitTube::write(void const* vaddr, size_t size)
{
ssize_t err, len;
do {
len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
err = len < 0 ? errno : 0;
} while (err == EINTR);
return err == 0 ? len : -err;
}
这样就将垂直同步信号经过socket发送到了连接的另一端,后面将继续分析SurfaceFlinger与应用进程是如何使用这条垂直信号的通路的。
2.4相关的对象
组合:
(1)SurfaceFlinger、HWComposwer
(2)DispSync、DispSyncThread
(3)DispSyncSource、EventThread、Connection
这些组合之间存在比较紧密的联系,下面总结的时候会画出它们之间的相互关系,总体来说:
组合(1):负责系统HWC硬件的启动,以及最原始的VSync信号的捕获;
组合(2):SF将捕获到的信号封装在DispSync里面(VSync信号源),DispSync通过内置的线程进行分发;
组合(3):SF创建的分支信号源(Android创建了两个分支EventThread线程),都是从DispSync(VSync信号源)里面分流出来的(DispSync将同步信号分发给DispSyncSource,DispSyncSource转发给EventThread,总体认为是一次分发),EventThread收到同步信号后分别负责将同步信号进行二次分发;
3 VSync信号的产生与传播
3.1 总结
看图,总结一下:
(1)在SF的init函数里面会创建一个HWComposer对象,该对象会打开HWC设备,并将HWComposer::hook_vsync作为HWC产生VSync信号的回调函数;
(2)HWComposer::hook_vsync会将VSync信号传递到SF.onVSyncReceived函数中;
(3)SF.onVSyncReceived函数调用DispSync.addResyncSample(DispSync可以认为是经过SF封装过的垂直同步信号的信号源)函数唤醒DispSync中的守护线程DispSyncThread;
(4)DispSyncThread.fireCallbackInvocations会将VSync信号分发到所有注册到DispSync.mEventListeners中满足条件的监听器的onDispSyncEvent函数中;
从上面的4个步骤可知,所有的VSync信号都是从DispSyncThread真正分发出去的(包括SF进程和所有的应用进程)。
(5)注册到DispSync中的回调由 (DispSyncSource, EventThread)二元组 组成,这两个是对应的,EventThread先启动并挂起,启动后等待需要VSync信号的客户端和它创建EventThread.Connection,并加到EventThread.mDisplayEventConnections中,同时唤醒EventThread,EventThread被唤醒后接收到VSync信号会将该事件通过EventThread.Connection.postEvent将同步信号时间分发到各个客户端Connection连接;
(6)Connection里面包含BitTube对象,该对象有一对直连的socket,一端发送,另一端就可以收到,SF和应用进程都是通过底层的loop(epoll机制)监听BitTube的ReceiveFd,然后把该同步信号分发到需要的地方。
3.2 回答最前面提出的问题
(1)VSync是如何产生的?
答:对于支持HWC的设备而言,HWC设备是在SF进程中打开并维护的,VSync信号由HWC设备产生,每次产生VSync信号会回调到HWComposer::hook_vsync函数。
(2)VSync最初是在哪个进程中捕获的?
答:VSync最初被HWComposer::hook_vsync传递到SF.onVSyncReceived函数中,并且经过SF一层封装成DispSync信号源。
剩下的两个问题等到下面分析SF进程和应用进程请求和获取VSync信号的时候再记录。