以下分析基于android 4.4代码
vsync信号的产生、分发涉及到以下几个类,先主要了解下他们各自的功能:
HWComposer:产生hardware vsync,post fb
VSyncThread : 如果没有硬件支持,那么通过软件方式模拟hw vsync
DispSync,DispSyncThread: 接受HWComposer的hw vsync信号作为校准,开始模拟产生vsync信号+偏移,并且会不时地进行校准,如postComposition后。
EventControlThread:sf中的一个线程,仅用来控制hw vsync开关
EventThread:负责分发vsync到sf或app
DispSyncSource:EventThread和DispSyncThread的信息传递者, 把vsync信号从DispSyncThread传递到EventThread;同时可以用来设置相位偏移参数。
在4.4之后,vsync信号不再完全由硬件产生,hw vsync信号主要用来做时间校准,vsync信号发生者是DispSyncThread, 当DispSyncThread产生的信号得到校准后,hw vsync会被关闭。
几个问题分析:
1.硬件vsync开启-关闭过程
(1)HWComposer在hwc_composer_device_1中注册回调:
mCBContext->procs.vsync = &hook_vsync;
mHwc->registerProcs(mHwc, &mCBContext->procs);
(2)vsync过来:HWComposer::hook_vsync => HWComposer::vsync
(3)HWComposer::vsync=>mEventHandler.onVSyncReceived(disp, timestamp);
mEventHandler即surfaceflinger
(4)SurfaceFlinger::onVSyncReceived:
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp); //加入样本,校准mPrimaryDispSync(DispSync),返回是否还需要hwsync if (needsHwVsync) { enableHardwareVsync(); //未同步,接续接受hw vsync } else { disableHardwareVsync(false); //已同步,关闭hw vsync }
开启或关闭硬vsync:
SurfaceFlinger::enableHardwareVsync() => mEventControlThread->setVsyncEnabled(true); //sf专门启动了一个线程EventControlThread来开关硬件vsync
2.DispSyncThread 信号的产生:
(1) 在sf类中声明一个成员变量:
class SurfaceFlinger { ... DispSync mPrimaryDispSync; ... }
(2) 构造函数里启动DispSyncThread线程
DispSync::DispSync() { mThread = new DispSyncThread(); mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); reset(); beginResync(); ... }
(3) 进入DispSyncThread::threadLoop(): 计算vsync周期,调用所有存在mEventListeners的Listener的callback
fireCallbackInvocations()方法中调用callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
mCallback的类型为DispSync::Callback
(4) mEventListeners的注册通过调用DispSync::addEventListener()
(5) 谁注册成为了vsync事件的监听者? 是DispSyncSource
DispSyncSource继承自DispSync::Callback, 在它setVSysncEnabled(true)中调用:
status_t err = mDispSync->addEventListener(mPhaseOffset, static_cast<DispSync::Callback*>(this)); //DispSyncSource把自己设为了DispSyncThread vsync信号的监听者 所以vsync消息传到了DispSyncSource中的onDispSyncEvent(nsecs_t when)中:
virtual void onDispSyncEvent(nsecs_t when) { sp<VSyncSource::Callback> callback; { Mutex::Autolock lock(mMutex); callback = mCallback; if (mTraceVsync) { mValue = (mValue + 1) % 2; ATRACE_INT("VSYNC", mValue); } } if (callback != NULL) { callback->onVSyncEvent(when); //又把vsync事件传递到了它自己的mCallback里, 这个mCallback 在EventThread::enableVSyncLocked()中设置, 就是EventThread, 这样vsync传递到了EventThread里 } }
(6)继续看谁又调用了DispSyncSource::setVSyncEnabled()?
是EventThread::enableVSyncLocked():
void EventThread::enableVSyncLocked() { if (!mUseSoftwareVSync) { // never enable h/w VSYNC when screen is off if (!mVsyncEnabled) { mVsyncEnabled = true; mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this)); //EventThread设为DispSyncSource的callback mVSyncSource->setVSyncEnabled(true); mPowerHAL.vsyncHint(true); } } mDebugVsyncEnabled = true; }
(7)EventThread::enableVSyncLocked()又被EventThread::waitForEvent()调用
Vector< sp<EventThread::Connection> > EventThread::waitForEvent( DisplayEventReceiver::Event* event) { ... // 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) { // we have at least one client, so we want vsync enabled // (TODO: this function is called right after we finish // notifying clients of a vsync, so this call will be made // at the vsync rate, e.g. 60fps. If we can accurately // track the current state we could avoid making this call // so often.) enableVSyncLocked(); } ... }
waitForEvent()的逻辑是:
接到vsync信号,但是当前EventThread中没有请求 vsync 的connection, EventThread向下不再监听vsync
EventThread中有请求 vsync 的connection, EventThread继续监听vsync
总结: vsync传递路径 DispSyncThread => DispSyncSource => EventThread
DispSyncSource: 这个类比较简单,其实就是vsync传递者, 同时负责传递相位偏移phase offset到dispsyncThread。
EventThread: 负责接收vsync, 分发给sf或者app
所以在Sf init中的代码就比较好理解了
// start the EventThread sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true); mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, false); mSFEventThread = new EventThread(sfVsyncSrc); //上面代码注册了两个vsync信号的监听者, 当vsync产生时,分发给EventThread,这里有两个,一个处理sf,一个处理app mEventQueue.setEventThread(mSFEventThread); // mEventControlThread = new EventControlThread(this); mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
3. 两个EventThread 线程是怎样把vsync分发给sf和app的?
(1)app与EventThread
EventThread里有一个 class Connection : public BnDisplayEventConnection,
BnDisplayEventConnection 继承自 IDisplayEventConnection
这个接口实现了:
getDataChannel()
setVsyncRate()
requestNextVsync()
App端请求vsync:
app端通过DisplayEventReceiver 中的sp<IDisplayEventConnection> mEventConnection 来requestNextVsync
mEventConnection实际上是BpDisplayEventConnection, 所以requestNextVsync是通过Binder通信从app端传递到EventThread并由它来处理。
同时通过mEventConnection->getDataChannel(); 保存一个BitTube类型的mDataChannel。
在EventThread端:
app调用createEventConnection创建DisplayEventConnection时,EventThread将这个connection注册到它的mDisplayEventConnections集合里
当vsync过来时,通知所有connection
App端接受vsync是通过建立连接时保存的那个BitTube:
//file:android_view_DisplayEventReceiver.cpp status_t NativeDisplayEventReceiver::initialize() { status_t result = mReceiver.initCheck(); f (result) { ALOGW("Failed to initialize display event receiver, status=%d", result); return result; } int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT, // 监听BitTube的fd,有数据时,调用handler this, NULL); if (rc < 0) { return UNKNOWN_ERROR; } return OK; }
所以app接受vsync信号是通过监听BitTube的fd, BitTube底层是通过socket实现。
(2) sf与EventThread
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, ALOOPER_EVENT_INPUT, MessageQueue::cb_eventReceiver, this); }
在sf进程中直接监听BitTube的fd,当有vsync过来时, 直接由SF的MessageQueue处理