必讀:
Android 12(S) 影像顯示系統 - 開篇
1 前言
這一篇文章,將繼續講解有關VSync的知識,前一篇文章 Android 12(S) 影像顯示系統 - SurfaceFlinger之VSync-上篇(十六)中,主要是分析了SurfaceFlinger啟動後VSync的一些初始化流程,以及vsync events的分發邏輯。
vsync events彙集到了兩個地方:
1. MessageQueue::vsyncCallback
==> VSYNC-sf
2. EventThread::onVSyncEvent
==> VSYNC-app & VSYNC-appSf
本篇中,將從一個簡單的demo出發,來具體分析,vsync events是如何傳遞到 ==> 真正需要的地方
2 可以監測vsync event的應用
2.1 程式碼位置
程式碼存放到了GitHub,自取哦
https://github.com/yrzroger/DisplayEventTracker
2.2 如何使用
1. 下載程式碼放到android原始碼目錄下
2. 執行 mm 編譯得到可執行檔 DisplayEventTracker
3. 將 DisplayEventTracker,adb push 到測試板的 /system/bin/ 目錄下
4. 在console下執行 DisplayEventTracker -h,可以檢視簡單的命令說明
usage: DisplayEventTracker [options]
------------------------------------ options ---------------------------------------------
[-i] vsync rate(default:1)
[-h] help
input 'r' to call requestNextVsync or input 'q' to exit when running
------------------------------------------------------------------------------------------
5. 示例命令
DisplayEventTracker // 預設vsync rate = 1, 每個vsync到來時都會收到該event
DisplayEventTracker -i 3 //表示vsync rate = 3, 每3個vsync才會通知一次
DisplayEventTracker -i 0 //除非呼叫requestNextVsync,否則不會收到vsync event,此時可以輸入‘r’來呼叫requestNextVsync
2.3 執行結果展示
我的測試板預設的螢幕重新整理率是60Hz,一個VSync間隔是16.67ms
結果一:預設setVsyncRate(1)
,每一個vsync event都會都到,可以看結果Vsync period大約是16.68ms
root:/ $ DisplayEventTracker
Vsync received: count=149
Vsync received: count=150 16.687281 ms (59.925879 Hz)
Vsync received: count=151 16.687281 ms (59.925879 Hz)
Vsync received: count=152 16.687281 ms (59.925879 Hz)
Vsync received: count=153 16.687281 ms (59.925879 Hz)
Vsync received: count=154 16.687281 ms (59.925879 Hz)
Vsync received: count=155 16.687281 ms (59.925879 Hz)
結果二:setVsyncRate(6)
,每間隔6個vsync events才投遞一次
root:/ $ DisplayEventTracker -i 6
Vsync received: count=540
Vsync received: count=546 100.102455 ms (9.989765 Hz)
Vsync received: count=552 100.102455 ms (9.989765 Hz)
Vsync received: count=558 100.102455 ms (9.989765 Hz)
Vsync received: count=564 100.102455 ms (9.989765 Hz)
Vsync received: count=570 100.102455 ms (9.989765 Hz)
Vsync received: count=576 100.102455 ms (9.989765 Hz)
Vsync received: count=582 100.102455 ms (9.989765 Hz)
結果三:setVsyncRate(0)
,每次呼叫requestNextVsync()
後才收到一次vsync event
root:/ $ DisplayEventTracker -i 6
130|RealtekStark:/ $ DisplayEventTracker -i 0
r
Vsync received: count=797
r
Vsync received: count=801 583.896606 ms (1.712632 Hz)
r
Vsync received: count=803 583.900635 ms (1.712620 Hz)
r
Vsync received: count=805 633.949219 ms (1.577413 Hz)
r
Vsync received: count=807 2002.051880 ms (0.499488 Hz)
r
Vsync received: count=809 1951.946533 ms (0.512309 Hz)
3 示例Demo原始碼解析
3.1 DisplayEventTracker類的定義
DisplayEventTracker定義很簡單,繼承自Thread,這意味著它可以開啟一個獨立的新執行緒,並在新執行緒中執行threadLoop()
中的處理邏輯。
class DisplayEventTracker : public Thread
{
public:
explicit DisplayEventTracker(int vsyncRate); // 建構函式
virtual ~DisplayEventTracker(); // 解構函式
void requestNextVsync(); // 請求下一個 vsync event
private:
virtual bool threadLoop();
virtual status_t readyToRun();
void processDisplayEvents();
// Display event handling
class DisplayEventCallback; // LooperCallback的實現類
std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver; // 接收 display events的核心成員
sp<Looper> mLooper;
int mVsyncRate; // 投遞 vsync events的間隔、頻率
};
3.2 DisplayEventTracker::readyToRun完成一些初始化設定,設定監聽和回撥
status_t DisplayEventTracker::readyToRun() {
// Register a display event receiver
// To receive ModeChanged and/or FrameRateOverrides events specify this in the constructor.
mDisplayEventReceiver = std::make_unique<DisplayEventReceiver>(); // 建立 DisplayEventReceiver 物件
status_t status = mDisplayEventReceiver->initCheck(); // 檢查 DisplayEventReceiver 初始化成功
if(status != NO_ERROR)
printf("Initialization of DisplayEventReceiver failed with status: %d", status);
mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT, // 新增待監測的fd,並設定回撥 DisplayEventCallback()
new DisplayEventCallback(), mDisplayEventReceiver.get()); //mDisplayEventReceiver.get()指標作為回撥時傳遞給回撥方法的資料
// setVsyncRate() sets the Event::VSync delivery rate.
// A value of 1 returns every Event::VSync.
// A value of 2 returns every other event, etc...
// a value of 0 returns no event unless requestNextVsync() has been called.
mDisplayEventReceiver->setVsyncRate(mVsyncRate); // 設定投遞 vsync event的頻率
return NO_ERROR;
}
3.3 新執行緒開啟,DisplayEventTracker::threadLoop中等待事件發生
bool DisplayEventTracker::threadLoop() {
processDisplayEvents();
return true;
}
void DisplayEventTracker::processDisplayEvents() {
// This will poll mDisplayEventReceiver and if there are new events it'll call
// displayEventCallback synchronously.
mLooper->pollOnce(-1);// 阻塞等待事件發生
}
threadLooper返回true,所以會反覆執行。
上面的邏輯就是典型的 Android Native Looper 機制,不熟悉的可以參見文章:
Android Native -- Message/Handler/Looper機制(原理篇)
Android Native -- Message/Handler/Looper機制(應用篇)
3.4 vsync event到來時,回撥 handleEvent
class DisplayEventTracker::DisplayEventCallback : public LooperCallback {
nsecs_t oldTimeStamp; // 記錄前一個vsync的時間
public:
DisplayEventCallback(): oldTimeStamp(0) {}
int handleEvent(int /* fd */, int /*events*/, void* data) {
DisplayEventReceiver* displayEventReceiver = (DisplayEventReceiver*)data;
constexpr int kBufferSize = 100;
DisplayEventReceiver::Event buffer[kBufferSize];
ssize_t numEvents;
do {
numEvents = displayEventReceiver->getEvents(buffer, kBufferSize); // 獲取事件
for (size_t i = 0; i < static_cast<size_t>(numEvents); i++) {
const auto& event = buffer[i];
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) { // 熱插拔事件
printf("Hotplug received: %s\n", event.hotplug.connected?"connected":"disconnected");
}
if(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { // vsync 事件
printf("Vsync received: count=%d\t", event.vsync.count); // 列印計數
if (oldTimeStamp) {
float t = float(event.header.timestamp - oldTimeStamp) / s2ns(1);
printf("%f ms (%f Hz)\n", t*1000, 1.0/t); //列印 vsync 事件間隔
} else {
printf("\n");
}
oldTimeStamp = event.header.timestamp; // 記錄事件
}
if(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE) { // 模式變化事件
printf("Mode change received\n");
}
}
} while (numEvents > 0);
return 1; // keep the callback
}
};
小結:
demo的整體流程是非常簡單的,本質就是通過Looper去監測DisplayEventReceiver::getFd()中的fd,當fd上有事件發生時,就會回撥到我們設定的函式。然後就可以從DisplayEventReceiver中getEvents獲取事件,判斷事件型別進行對應處理了
DisplayEventReceiver由是個啥東東?它為什麼可以收到vsync event呢?莫急,稍後分析
4 DisplayEventReceiver相關原理分析
DisplayEventReceiver建立並註冊與SurfaceFlinger的事件連線。可用來監測VSync、HotPlug、ModeChange、FrameRateOverride事件。
4.1 類定義
4.2 主要方法解釋
DisplayEventReceiver建構函式
可以根據需求來指定VsyncSource,並設定EventRegistrationFlags來決定是否接收ModeChanged和FrameRateOverrides事件。
[/frameworks/native/libs/gui/include/gui/ISurfaceComposer.h]
enum VsyncSource {
eVsyncSourceApp = 0,
eVsyncSourceSurfaceFlinger = 1
};
enum class EventRegistration {
modeChanged = 1 << 0,
frameRateOverride = 1 << 1,
};
status_t setVsyncRate(uint32_t count)
設定投遞vsync events的頻率,設定1代表每個vsync event均被投遞,設定2代表每隔一個投遞一次,依次類推 ...
設定0代表只有呼叫requestNextVsync()後才會投遞一次vsync event
status_t requestNextVsync()
請求下一個vsync event,在vsync rate大於0的時候,這個函式呼叫無效
int getFd() const
獲取用於接收事件的檔案描述符
ssize_t getEvents(Event* events, size_t count)
當監測到有事件發生時,通過它獲取具體的事件列表,函式返回值就是事件的數量
ssize_t sendEvents(Event const* events, size_t count)
傳送事件,函式返回值就是事件的數量
本文作者@二的次方 2022-04-27 釋出於部落格園
4.3 DisplayEventReceiver工作原理,事件是怎麼傳遞過來的?
先看看它的建構函式的具體實現
[/frameworks/native/libs/gui/DisplayEventReceiver.cpp]
DisplayEventReceiver::DisplayEventReceiver(
ISurfaceComposer::VsyncSource vsyncSource,
ISurfaceComposer::EventRegistrationFlags eventRegistration) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService()); // 獲取SurfaceFLinger服務
if (sf != nullptr) {
mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration); // 建立遠端事件連線
if (mEventConnection != nullptr) {
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get()); // 傳遞 BitTube
}
}
}
核心的處理應該是createDisplayEventConnection
和stealReceiveChannel
,下面分別看看這兩個操作具體做了啥子
4.3.1 SurfaceFlinger::createDisplayEventConnection
這個方法通過Binder IPC跨程式,一路飛奔,直到SurfaceFlinger核心服務 SurfaceFlinger::createDisplayEventConnection
[/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource,
ISurfaceComposer::EventRegistrationFlags eventRegistration) {
const auto& handle = // 判斷選哪個 vsyncSource
vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
// 建立 DisplayEventConnection
return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}
mSfConnectionHandle
和mAppConnectionHandle
是在initScheduler時建立的scheduler::ConnectionHandle
物件,前一篇文章中有分析過。
通過這兩個handle可以在Scheduler::mConnections
中找到和他們分別對應的Connection
,即
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {
sp<EventThreadConnection> connection;
std::unique_ptr<EventThread> thread;
};
4.3.2 Scheduler::createDisplayEventConnection
先看程式碼
[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
std::lock_guard<std::mutex> lock(mConnectionsLock);
RETURN_IF_INVALID_HANDLE(handle, nullptr);
return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
}
根據handle,從Scheduler::mConnections
取出對應的EventThread
物件,繼續呼叫 Scheduler::createConnectionInternal
[/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp]
sp<EventThreadConnection> Scheduler::createConnectionInternal(
EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}
繼續去呼叫了 EventThread::createEventConnection
[/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
物件,並返回給呼叫者。如下圖繼承關係,保證了DisplayEventReceiver
可以取得EventThreadConnection
物件的遠端代理,儲存在成員sp<IDisplayEventConnection> mEventConnection
流程繼續,建立EventThreadConnection
物件,第一次被引用時會進到onFirstRef
中進行註冊
void EventThreadConnection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
mEventThread->registerDisplayEventConnection(this);
}
再轉到EventThread::registerDisplayEventConnection
中,就是把這個connecttion儲存到EventThread::mDisplayEventConnections
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
// this should never happen
auto it = std::find(mDisplayEventConnections.cbegin(),
mDisplayEventConnections.cend(), connection);
if (it != mDisplayEventConnections.cend()) { // 判斷是否已經存在
ALOGW("DisplayEventConnection %p already exists", connection.get());
mCondition.notify_all();
return ALREADY_EXISTS;
}
mDisplayEventConnections.push_back(connection);// 儲存到 mDisplayEventConnections 這個vector陣列中
mCondition.notify_all();
return NO_ERROR;
}
DisplayEventReceiver已經和SurfaceFlinger服務端的Scheduler建立了關係,再回到DisplayEventReceiver的建構函式接著分析下面的操作
[/frameworks/native/libs/gui/DisplayEventReceiver.cpp]
// DisplayEventReceiver建構函式
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get()); // 傳遞跨程式資料傳遞的物件 BitTube
下一步建立了一個BitTube
物件,然後呼叫了mEventConnection->stealReceiveChannel
,這個方法會走到
[/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp ]
status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
outChannel->setReceiveFd(mChannel.moveReceiveFd());// resets this BitTube's receive file descriptor to receiveFd
outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd()))); // resets this BitTube's send file descriptor to sendFd
return NO_ERROR;
}
這使用到BitTube的跨程式傳遞資料的方式,基本原理可以參考:Android 12(S) 影像顯示系統 - 基礎知識之 BitTube
到這裡,我們可以清晰的看到,DisplayEventReceiver與SurfaceFlinger建立起來了一條跨程式傳遞事件的通道:BitTube中封裝的socketpair (receive fd & send fd)
4.4 事件的傳遞、分發
通訊線路已建立,接下來就要把事件經過這條道路向外傳遞了。
上一篇文章中曾講到過
收到vsync events的彙集到了兩個地方:
1. MessageQueue::vsyncCallback ==> VSYNC-sf
2. EventThread::onVSyncEvent ==> VSYNC-app & VSYNC-appSf
我們這裡只看EventThread::onVSyncEvent
[/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp,
nsecs_t deadlineTimestamp) {
...
// 包裝為 DisplayEventReceiver::Event物件,存入 mPendingEvents 尾部
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
expectedVSyncTimestamp, deadlineTimestamp, vsyncId));
mCondition.notify_all();
}
EventThread收到 vsync event回撥事件後,放入mPendingEvents
這個待處理的事件佇列中,然後喚醒等待的處理執行緒,即在EventThread::threadMain
[/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
// using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;
DisplayEventConsumers consumers; // consumers是一個EventThreadConnection陣列
while (mState != State::Quit) {
std::optional<DisplayEventReceiver::Event> event;
// Determine next event to dispatch.
if (!mPendingEvents.empty()) {
event = mPendingEvents.front(); // 取出 mPendingEvents 頭部第一個待處理的 event
mPendingEvents.pop_front(); // 刪除開頭元素
switch (event->header.type) { // 判斷是什麼型別的事件
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: // 熱插拔事件
if (event->hotplug.connected && !mVSyncState) {
mVSyncState.emplace(event->header.displayId);
} else if (!event->hotplug.connected && mVSyncState &&
mVSyncState->displayId == event->header.displayId) {
mVSyncState.reset();
}
break;
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: // VSYNC 事件
if (mInterceptVSyncsCallback) {
// mInterceptVSyncsCallback 是在SurfaceFlinger::initScheduler中createConnection時一路傳遞過來的
// 這個回撥會通知到SurfaceFlinger
mInterceptVSyncsCallback(event->header.timestamp);
}
break;
}
}
bool vsyncRequested = false;
// Find connections that should consume this event.
auto it = mDisplayEventConnections.begin(); // mDisplayEventConnections 中儲存了所有與這個EventThread建立的連線
while (it != mDisplayEventConnections.end()) { // 遍歷所有Connection
if (const auto connection = it->promote()) {
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;//是否請求vsync
if (event && shouldConsumeEvent(*event, connection)) { // 判斷是否需要分發事件通知這個connection
consumers.push_back(connection);
}
++it;
} else {
it = mDisplayEventConnections.erase(it);
}
}
if (!consumers.empty()) {
dispatchEvent(*event, consumers);// 分發事件,最終是使用BitTube傳送資料,通知connection
consumers.clear();
}
State nextState;
if (mVSyncState && vsyncRequested) {
// synthetic = True if VSYNC should be faked, e.g. when display is off. 螢幕關閉產生虛假的VSYNC
nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
} else {
ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
nextState = State::Idle; // 進入Idle阻塞等待
}
if (mState != nextState) {
if (mState == State::VSync) {
mVSyncSource->setVSyncEnabled(false); // 關閉 vsync
} else if (nextState == State::VSync) {
mVSyncSource->setVSyncEnabled(true); // 開啟 vysnc ,作用於CallbackRepeater,迴圈去schedule next vsync
}
mState = nextState;
}
if (event) {
continue;
}
// Wait for event or client registration/request.
if (mState == State::Idle) {
mCondition.wait(lock);
} else {
// Generate a fake VSYNC after a long timeout in case the driver stalls. When the
// display is off, keep feeding clients at 60 Hz.
const std::chrono::nanoseconds timeout =
mState == State::SyntheticVSync ? 16ms : 1000ms;
if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
if (mState == State::VSync) {
ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
std::string debugInfo = "VsyncSource debug info:\n";
mVSyncSource->dump(debugInfo);
// Log the debug info line-by-line to avoid logcat overflow
auto pos = debugInfo.find('\n');
while (pos != std::string::npos) {
ALOGW("%s", debugInfo.substr(0, pos).c_str());
debugInfo = debugInfo.substr(pos + 1);
pos = debugInfo.find('\n');
}
}
LOG_FATAL_IF(!mVSyncState);
const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
const auto deadlineTimestamp = now + timeout.count();
const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
const int64_t vsyncId = [&] {
if (mTokenManager != nullptr) {
return mTokenManager->generateTokenForPredictions(
{now, deadlineTimestamp, expectedVSyncTime});
}
return FrameTimelineInfo::INVALID_VSYNC_ID;
}();
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
++mVSyncState->count, expectedVSyncTime,
deadlineTimestamp, vsyncId));
}
}
}
}
EventThread::threadMain
程式碼邏輯上也比較清晰,主體就是從mPendingEvents
這個待處理的事件佇列中取出event,讓後經過判斷處理後通知到對應的connections
本文作者@二的次方 2022-04-27 釋出於部落格園
簡單說說
EventThread::shouldConsumeEvent
這個方法就如同它的名字,判斷是否去消費這個事件,說白了就是判斷這個事件是否要分發通知給指定的connection。
引數event就是當前發生的,準備分發的事件
引數connection就是客戶端註冊到EventThread中的connection,其中就包裝了用於跨程式通訊的BitTube物件
對於VSYNC事件,在這個函式中實現了setVsyncRate
中設定的分發頻率
[ /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp]
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
const sp<EventThreadConnection>& connection) const {
const auto throttleVsync = [&] {
return mThrottleVsyncCallback &&
mThrottleVsyncCallback(event.vsync.expectedVSyncTimestamp, connection->mOwnerUid);
};
switch (event.header.type) {
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: // 熱插拔事件
return true;
case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {// mode change事件
return connection->mEventRegistration.test( //接收者設定了modeChanged標誌才會分發
ISurfaceComposer::EventRegistration::modeChanged);
}
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: // VSYNC事件
switch (connection->vsyncRequest) { // setVsyncRate設定分發的頻率
case VSyncRequest::None: // rate==0,不分發
return false;
case VSyncRequest::SingleSuppressCallback:// requestNextVsync 有請求時case
connection->vsyncRequest = VSyncRequest::None;
return false;
case VSyncRequest::Single: { // requestNextVsync 有請求時case
if (throttleVsync()) {
return false;
}
connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
return true;
}
case VSyncRequest::Periodic: // rate==1,週期性,每個VSYNC事件都分發通知
if (throttleVsync()) {
return false;
}
return true;
default:
// We don't throttle vsync if the app set a vsync request rate
// since there is no easy way to do that and this is a very
// rare case
// 根據setVsyncRate設定分發的頻率,週期性的計數,每connection->vsyncRequest個分發一個
return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
}
case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
[[fallthrough]];
case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH: // frame rate override flush事件
return connection->mEventRegistration.test(// 判斷接收者設定了frameRateOverride標誌才會分發
ISurfaceComposer::EventRegistration::frameRateOverride);
default:
return false;
}
}
EventThread::dispatchEvent
當前面判斷某一個事件應該分發出去後,接下來就是去實際把事件分發出去,通知到接收者了
最終的事件是通過呼叫EventThreadConnection::postEvent
==> DisplayEventReceiver::sendEvents
==> gui::BitTube::sendObjects
BitTube跨程式通知到接收者
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
// 注意:using DisplayEventConsumers = std::vector<sp<EventThreadConnection>>;
// 從consumers陣列中遍歷EventThreadConnection
for (const auto& consumer : consumers) {
DisplayEventReceiver::Event copy = event;
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
}
switch (consumer->postEvent(copy)) { // postEvent分發事件==>EventThreadConnection::postEvent
...
}
}
}
DispSyncSource::setVSyncEnabled
這個方法去call mRegistration.schedule
== > VSyncCallbackRegistration::schedule
去安排下一次的Vsync events
大概如此,從而週期性的收到vsync events , 不多講了
經過上面流程的分析,事件通過BitTube::sendObjects
跨程式通知到接收者,接收者通過監聽BitTube::mReceiveFd
,並在接收到事件時呼叫BitTube::recvObjects
就可以取出事件,做後續處理了
總結一個不是很準確的圖,我也不知道該咋表達了,哈