前面兩篇文章分析了應用層對Vsync的註冊與接收,收到Vsync之後應用層便開始View的繪製
我們先來回顧一下大致的流程:
- 首先應用層想要繪製UI,則需要向native層註冊接收下一個到來的Vsync,註冊的過程是通過EventThreadConnection的Bp端最終調用到SurfaceFlinger進程的EventThread的requestNextVsync函數
- EventThread是用來專門處理各種事件的,除了Vsync,還有Hotplug和ConfigChanged,EventThread有兩個,一個名字叫”app“,一個名字叫”sf“
- EventThreadConnection代表應用層到SurfaceFlinger進程的連接,每一個上層的ViewRootImpl都對應一個EventThreadConnection,因爲每個View視圖都需要Vsync來開啓繪製工作
- EventThread並不是一個線程,它的內部有一個線程,這個線程就是用來處理底層Vsync的接收以及分發的,這個線程是一個死循環,當它沒收到事件請求時會通過C++條件變量調用wait陷入等待狀態
- 應用層請求Vsync的過程其實就是通過這個條件變量調用notify喚醒EventThread內部這個線程,然後從mPendingEvents中獲取到Vsync信息分發給感興趣的進程
我們前兩篇文章大概就分析了這些,本篇文章就來探究mPendingEvents中的Vsync是哪來的,以及EventThread內部這個線程的工作原理
EventThread的創建是在SurfaceFlinger的init函數中
void SurfaceFlinger::init() {
......
// start the EventThread
mScheduler =
getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
mRefreshRateConfigs);
mAppConnectionHandle =
mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
resyncCallback,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
resyncCallback, [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
......
}
這個函數中首先創建了Scheduler,接着通過Scheduler創建了兩個Scheduler::ConnectionHandle,從名字能看出來,一個負責app處理,一個負責surfaceflinger處理,EventThread也會創建兩個,剛好對應這兩個ConnectionHandle
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) {
......
}
EventThread的構造函數裏面先不忙分析,先來看看它構造函數中初始化的mVSyncSource,類型爲VSyncSource,看它是如何創建的
回到前面創建Scheduler::ConnectionHandle的函數:
createConnection
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
std::unique_ptr<EventThread> eventThread =
makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
std::move(interceptCallback));
......
return mConnections[id]->handle;
}
std::unique_ptr<EventThread> Scheduler::makeEventThread(
const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
std::unique_ptr<VSyncSource> eventThreadSource =
std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
std::move(interceptCallback), connectionName);
}
上面兩個函數就會創建VSyncSource並傳遞到EventThread中,
原來創建的是VSyncSource的子類DispSyncSourc,創建DispSyncSource時又需要一個DispSync,DispSync則是直接傳遞的mPrimaryDispSync.get()
那麼現在就需要搞清楚mPrimaryDispSync是什麼時候創建的
找到了,mPrimaryDispSync是在Scheduler的構造函數中創建的
Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
const scheduler::RefreshRateConfigs& refreshRateConfig)
: mHasSyncFramework(running_without_sync_framework(true)),
mDispSyncPresentTimeOffset(present_time_offset_from_vsync_ns(0)),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mRefreshRateConfigs(refreshRateConfig) {
// Note: We create a local temporary with the real DispSync implementation
// type temporarily so we can initialize it with the configured values,
// before storing it for more generic use using the interface type.
auto primaryDispSync = std::make_unique<impl::DispSync>("SchedulerDispSync");
primaryDispSync->init(mHasSyncFramework, mDispSyncPresentTimeOffset);
mPrimaryDispSync = std::move(primaryDispSync);
......
}
創建DispSync之後調用了它的init函數,來看看DispSync的構造函數
DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) {
// This flag offers the ability to turn on systrace logging from the shell.
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.dispsync_trace_detailed_info", value, "0");
mTraceDetailedInfo = atoi(value);
mThread = new DispSyncThread(name, mTraceDetailedInfo);
}
這裏面創建了一個線程DispSyncThread,這個線程構造函數中只是對一些值做了初始化,這個線程重點是它的threadLoop函數,這個函數現在先不忙看,等下分析了EventThread之後在回頭針對性看
好了EventThread的VSyncSource就創建好了,實際上是一個DispSyncSource對象,DispSyncSource內部有一個DispSync,DispSync內部有一個線程DispSyncThread,其實我們光看名字應該能夠猜測,這幾個類都是用來處理VSync的
接着回到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) {
......
mVSyncSource->setCallback(this);
mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
threadMain(lock);
});
......
}
這個函數有兩個重點,1.給VSyncSource設置回調,2.創建一個線程,並調用threadMain函數
首先看設置回調:
class VSyncSource {
public:
class Callback {
public:
virtual ~Callback() {}
virtual void onVSyncEvent(nsecs_t when) = 0;
};
.....
}
這個回調的類型是VSyncSource::Callback,它只有一個函數onVSyncEvent,這個函數被EventThread實現了,也就是說會有某些情況發生之後EventThread會調用onVSyncEvent函數,我們根據這個函數的名字可以猜測一下可能是收到來自硬件的VSync後會回調此函數
回調設置之後會創建一個線程調用threadMain函數,這是EventThread核心函數,這個函數代碼很多,在看這個函數之前,我們先了解一下這個函數用到的重要變量的含義,主要有三個容器進行存取數據的操作,DisplayEventConsumers consumers,mPendingEvents,mDisplayEventConnections,它們都定義在EventThread.h中
//EventThread.h
using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;
std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
std::vector<wp<EventThreadConnection>> mDisplayEventConnections GUARDED_BY(mMutex);
GUARDED_BY用來保證線程安全,類似java同步鎖synchronized的用法
consumers類型爲DisplayEventConsumers,這是一個vector,裏面放的是EventThreadConnection
mPendingEvents是一個deque隊列,裏面放的是DisplayEventReceiver::Event
mDisplayEventConnections也是一個vector,裏面放的也是EventThreadConnection
這裏雖然consumers和mDisplayEventConnections都是存儲EventThreadConnection,但是consumers存儲的是請求了Vsync的connection,mDisplayEventConnections存儲的是所有和surfaceFlinger進程建立連接的connection
這三個重要容器看了之後再來看看mState這個變量,這是用來描述EventThread的線程狀態的,mState類型爲State,定義在EventThread.h中
enum class State {
Idle,
Quit,
SyntheticVSync,
VSync,
};
State mState GUARDED_BY(mMutex) = State::Idle;
一共有4種狀態,Idle表示空閒,Quit表示退出,SyntheticVSync表示合成VSync(滅屏時會是這種狀態),VSync表示請求VSync
EventThread線程狀態看完之後再來看一個VSyncRequest
enum class VSyncRequest {
None = -1,
Single = 0,
Periodic = 1,
// Subsequent values are periods.
};
這個枚舉類用來表示VSync的請求類型,有三種,None表示當前沒有VSync請求,Single表示這是一次性VSync請求(請求一次,接收一次),Periodic表示這是週期性VSync請求(請求一次可以一直接收)
對threadMain函數中用到的重要變量有了基本瞭解之後,現在我們再來看這個函數:
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
//存儲EventThreadConnection的vector,consumers表示即將消費
//事件的connection集合
DisplayEventConsumers consumers;
//只要不退出,就一直循環,相當於死循環
while (mState != State::Quit) {
//構造一個待分發的Event
std::optional<DisplayEventReceiver::Event> event;
// mPendingEvents是一個vector,存儲即將處理的
//DisplayEventReceiver::Event
if (!mPendingEvents.empty()) {
//獲取頭部Event
event = mPendingEvents.front();
//並將頭部Event彈出
mPendingEvents.pop_front();
//根據Event的類型,做不同處理,我們只關心VSYNC類型
switch (event->header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
......
break;
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
if (mInterceptVSyncsCallback) {
mInterceptVSyncsCallback(event->header.timestamp);
}
break;
}
}
//是否有vsync請求,默認false
bool vsyncRequested = false;
// 從mDisplayEventConnections中查詢應該接收Event的
//EventThreadConnection,這是個vector遍歷操作
auto it = mDisplayEventConnections.begin();
while (it != mDisplayEventConnections.end()) {
//弱指針升級強指針,當對象已經銷燬或者準備銷燬則返回false
if (const auto connection = it->promote()) {
//如果有一個connection的vsyncRequest不爲None則
//vsyncRequested爲true
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
//如果event不爲空並且shouldConsumeEvent返回true
//則將connection加入到consumers,等待消費event,
//shouldConsumeEvent的實現很簡單,對於VSYNC類型的事件,
//只要VSyncRequest的類型不是None就返回true
if (event && shouldConsumeEvent(*event, connection)) {
//加入consumers
consumers.push_back(connection);
}
++it;
} else {
//如果connections已經銷燬則移除它
it = mDisplayEventConnections.erase(it);
}
}
if (!consumers.empty()) {
//如果consumers不爲空則調用dispatchEvent
//爲consumers中的每個connection分發事件
//後面分析...
dispatchEvent(*event, consumers);
//分發之後清空consumers
consumers.clear();
}
State nextState;
//如果有vsync的請求
if (mVSyncState && vsyncRequested) {
//判斷是SyntheticVSync還是VSync類型的VSync
//mVSyncState->synthetic在滅屏時被賦值爲true,亮屏
//時爲false
nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
} else {
ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
//沒有vsync則狀態爲State::Idle
nextState = State::Idle;
}
//兩個狀態不等說明有兩種可能,1.從State::VSync變爲其他
//2.從其他變爲State::VSync
if (mState != nextState) {
//情況1
if (mState == State::VSync) {
//後面分析...
mVSyncSource->setVSyncEnabled(false);
//情況2
} else if (nextState == State::VSync) {
mVSyncSource->setVSyncEnabled(true);
}
mState = nextState;
}
//如果有事件則繼續循環
if (event) {
continue;
}
// 沒有事件並且當前狀態爲State::Idle
if (mState == State::Idle) {
//則通過條件變量陷入等待
mCondition.wait(lock);
} else {
//如果沒有事件並且當前狀態不爲空閒,這種情況是硬件不知什麼原因沒
//有發送VSync上來,需要僞造VSync信號,頻率爲滅屏時16ms,亮屏
//1000ms
const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms;
if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
//將僞造的VSync放入mPendingEvents,準備分發
mPendingEvents.push_back(makeVSync(mVSyncState->displayId,
systemTime(SYSTEM_TIME_MONOTONIC),
++mVSyncState->count));
}
}
}
}
threadMain函數大概分析完了,代碼是挺多的,仔細看看註釋,結合前面單獨對重要數據的分析,會發現邏輯是比較簡單,總結一下:
- threadMain首先會開啓一個死循環,這個循環會一直處理事件
- 從mPendingEvents頭部獲取VSYNC事件Event
- 遍歷mDisplayEventConnections,找到其中所有vsyncRequest不爲None的connection,並將這些connection放入consumers
- 調用dispatchEvent(*event, consumers)分發事件,事件會分發給consumers中的所有connection
- 根據mState和nextState的對比,選擇setVSyncEnabled(false)還是(true),當從State::VSync變爲其他狀態時調用setVSyncEnabled(false),當從其他狀態變爲State::VSync時調用setVSyncEnabled(true),mState和nextState的對比其實是起到一個開關作用
- 如果沒有事件並且線程狀態爲State::Idle,則通過條件變量mCondition讓線程陷入等待,如果沒有事件並且線程狀態不爲State::Idle時則需要僞造VSync發送給請求者
前面兩篇文章分析了應用層想要進行UI繪製則需要向surfaceFlinger進程請求VSync,等待下一個VSync到來之後通知應用進行繪製,應用層請求VSync的過程就是通過條件變量的notify函數,喚醒threadMain中陷入等待的這個死循環,剛剛threadMain函數的分析又知道了這個死循環主要工作就是從mPendingEvents獲取到事件,然後調用dispatchEvent函數分發給感興趣的connection,何爲感興趣的connection?就是它的vsyncRequest不爲None,dispatchEvent函數就會將
到這裏還遺留了幾個關鍵地方沒有分析,1.mPendingEvents裏的事件是怎麼來的,2.setVSyncEnabled函數的具體作用
我們先來看setVSyncEnabled這個函數的具體作用,這個函數定義在DispSyncSource中,DispSyncSource我們前面分析過,是在創建EventThread的時候創建的,並且DispSyncSource內部還創建了一個DispSync,DispSync內部開啓了一個線程DispSyncThread,這個線程有個重要的threadLoop函數我們還留着沒分析
先看這個函數:
DispSyncSource.setVSyncEnabled
void DispSyncSource::setVSyncEnabled(bool enable) {
std::lock_guard lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this),
mLastCallbackTime);
......
} else {
status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this),
&mLastCallbackTime);
......
}
mEnabled = enable;
}
這個函數其實就是添加和移除監聽器,那麼這個監聽器到底在監聽什麼?監聽到了之後又調用它的哪個回調函數?
回調哪個函數這很簡單,我們看看DispSync.h就知道了
class DispSync {
public:
class Callback {
public:
Callback() = default;
virtual ~Callback();
virtual void onDispSyncEvent(nsecs_t when) = 0;
......
}
就是這個函數onDispSyncEvent,也就是說當通過setVSyncEnabled添加的監聽器,監聽到某件事發生之後就會回調DispSyncSource的onDispSyncEvent函數,那現在就需要找到添加的這個監聽器在監聽什麼?
來看看DispSync添加監聽器之後做了什麼
mDispSync->addEventListener
status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback,
nsecs_t lastCallbackTime) {
...
for (size_t i = 0; i < mEventListeners.size(); i++) {
if (mEventListeners[i].mCallback == callback) {
return BAD_VALUE;
}
}
EventListener listener;
listener.mName = name;
listener.mPhase = phase;
listener.mCallback = callback;
.....
mEventListeners.push_back(listener);
mCond.signal();
return NO_ERROR;
}
我省略一大段EventListener time的計算,不想去分析了,剩下的代碼無非就是根據添加的監聽callback,name等構造一個EventListener,然後存儲到mEventListeners這個Vector中,mCond.signal類似條件變量,也是一個喚醒/等待機制,那它是要喚醒什麼呢?
前面DispSync創建時就開啓了一個線程DispSyncThread,這個線程也類似EventThread內部的線程,是一個死循環,這個線程是真正分發Vsync信號的線程,所有應用程序以及surfaceFlinger註冊的Vsync都是通過這個線程的死循環中分發出去的,限於篇幅,關於DispSyncThread的相關分析留到下一篇文章