1.1.1 VSync訊號的處理
經過上一小節的分析,現在我們已經明白了系統是如何通過硬體裝置或者軟體類比來產生VSync訊號的,也明白了它的流轉過程。VSync最終會被EventThread::threadLoop()分發給各監聽者,在目前的版本中是MessageQueue。
MessageQueue通過與EventThread建立一個Connection來監聽事件,簡圖如下:
圖 11?35 Connection代表了EventThread和對事件感興趣的對象的串連
對VSYNC等事件感興趣的對象,比如MessageQueue,首先要通過EventThread::createEventConnection()來建立一個串連,實際上就是產生了一個EventThread::Connection對象。這個對象將對雙方產生如下影響:
l 當Connection::onFirstRef()時,它會主動調用EventThread::registerDisplayEventConnection()來把自己加入到mDisplayEventConnections中,這是保證事件發生後EventThread能找到“串連”的關鍵一步
l 當MessageQueue得到Connection後,它會馬上調用getDataChannel來獲得一個BitTube。從邏輯關係上看,Connection只是雙方業務上串連,而BitTube則是資料轉送通道,各種Event資訊就是通過這裡傳輸的
void MessageQueue::setEventThread(const sp<EventThread>&eventThread)
{
mEventThread =eventThread;
mEvents = eventThread->createEventConnection(); //建立一個Connection
mEventTube = mEvents->getDataChannel();//馬上擷取BitTube
mLooper->addFd(mEventTube->getFd(), 0,ALOOPER_EVENT_INPUT, MessageQueue::cb_eventReceiver, this);
}
從扮演的角色上來看,EventThread是Server,不斷地往Tube中寫入資料;而MessageQueue是Client,負責讀取資料。可能有人會很好奇,MessageQueue如何得知有Event到來,然後去讀取它呢?答案就是它們之間的資料讀寫入模式採用的是Socket(AF_UNIX域)。
上面這個函數的末尾,通過Looper添加了一個fd,這實際上就是Socket pair中的一端。然後Looper將這個fd與其callback函數(即MessageQueue::cb_eventReceiver)加入全域的mRequests進行管理。
KeyedVector<int, Request> mRequests;
這個Vector會集中所有需要監測的fd,這樣當Looper進行pollInner時,只要有事件需要處理,它就可以通過回呼函數通知“接收者”。這裡面的實現細節主要包括BitTube.cpp和Looper.cpp,有興趣的讀者可以自行研究下。