HWComposer模塊產生VSync信號後要經過分發才能送達到關心VSync事件的模塊中去。VSync信號分發大致流程爲HWComposer->SurfaceFlinger->DispSync->DispSyncSource->各個具體模塊。下面具體分析下這個流程。
在上一篇文章中分析到硬件或者軟件VSync信號產生時,會回調SurfaceFlinger的onVSyncReceived函數,來看看這個函數:
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);
}
}
- mPrimaryDispSync類型爲DispSync,在構造的時候會創建DispSyncThread
DispSync::DispSync() :
mRefreshSkipCount(0),
mThread(new DispSyncThread()) {
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
reset();
beginResync();
if (kTraceDetailedInfo) {
// If we're not getting present fences then the ZeroPhaseTracer
// would prevent HW vsync event from ever being turned off.
// Even if we're just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
if (!kIgnorePresentFences) {
addEventListener(0, new ZeroPhaseTracer());
}
}
}
- 調用DispSync的addResyncSample方法,最終會去喚醒DispSyncThread線程
bool DispSync::addResyncSample(nsecs_t timestamp) {
Mutex::Autolock lock(mMutex);
size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
mNumResyncSamples++;
} else {
mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
}
updateModelLocked();
if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {
resetErrorLocked();
}
if (kIgnorePresentFences) {
// If we don't have the sync framework we will never have
// addPresentFence called. This means we have no way to know whether
// or not we're synchronized with the HW vsyncs, so we just request
// that the HW vsync events be turned on whenever we need to generate
// SW vsync events.
return mThread->hasAnyEventListeners();
}
return mPeriod == 0 || mError > kErrorThreshold;
}
- 調用updateModelLocked函數
- 計算是否需要開啓硬件VSync,進行同步
void DispSync::updateModelLocked() {
if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
......
mThread->updateModel(mPeriod, mPhase);
}
}
- 成員變量mThread爲DispSyncThread類的對象
- 調用DispSyncThread類pdateModel方法
void updateModel(nsecs_t period, nsecs_t phase) {
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
mCond.signal();
}
- 該方法主要設置成員變量mPeriod、mPhase
- 然後在喚醒線程循環
virtual bool threadLoop() {
status_t err;
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
nsecs_t nextEventTime = 0;
while (true) {
Vector<CallbackInvocation> callbackInvocations;
nsecs_t targetTime = 0;
{ // Scope for lock
Mutex::Autolock lock(mMutex);
......
callbackInvocations = gatherCallbackInvocationsLocked(now);
}
if (callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations);
}
}
return false;
}
- 通過gatherCallbackInvocationsLocked得到監聽者集合
- 通過fireCallbackInvocations調用監聽者回調函數
DispSync的回調函數在哪裏註冊,我們在看看DispSyncSource的setVSyncEnabled函數
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->addEventListener(mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
strerror(-err), err);
}
//ATRACE_INT(mVsyncOnLabel.string(), 1);
} else {
status_t err = mDispSync->removeEventListener(
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error unregistering vsync callback: %s (%d)",
strerror(-err), err);
}
//ATRACE_INT(mVsyncOnLabel.string(), 0);
}
mEnabled = enable;
}
- DispSyncSource類繼承於DispSync::Callback
- 調用DispSync->addEventListener註冊回調,當DispSyncSource收到DispSync的VSync信號時,會回調整onDispSyncEvent函數
virtual void onDispSyncEvent(nsecs_t when) {
sp<VSyncSource::Callback> callback;
{
Mutex::Autolock lock(mCallbackMutex);
callback = mCallback;
if (mTraceVsync) {
mValue = (mValue + 1) % 2;
ATRACE_INT(mVsyncEventLabel.string(), mValue);
}
}
if (callback != NULL) {
callback->onVSyncEvent(when);
}
}
- 這個函數最終還是調用VSyncSource::Callback的onVSyncEvent函數。
- VSyncSource::Callback函數的註冊是通過調用DispSyncSource的setCallback註冊。
DispSyncSource的setCallback函數在哪裏調用的呢,要解答這個問題,還是得回到SurfaceFlinger的init函數裏,以sfVsyncSrc爲例。
void 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);
......
}
- 以sfVsyncSrc爲參數創建EventThread對象
- 在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));
mVSyncSource->setVSyncEnabled(true);
}
}
mDebugVsyncEnabled = true;
sendVsyncHintOnLocked();
}
- EventThread繼承VSyncSource::Callback接口,實現了onVSyncEvent函數
- 調用mVSyncSource的setCallback函數設置回調
- 調用mVSyncSource的setVSyncEnabled函數使能VSync信號的監聽
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();
}
- EventThread收到VSync信號後,發送廣播消息,喚醒相關線程
- 最終EventThread將VSnc信號傳遞給MessageQueue