App與SurfaceFlinger是不同的進程,它們之間傳遞VSync的話涉及到進程間通信,而且VSync頻率很高,App很多,所以VSync的分發效率要很高才行。Linux進程間通信方式總共就那么幾種,Android選擇了Domain Socket,應該是因為其高效、簡單、且有序吧,并將其封裝成了更易用的BitTube。
VSync-app/sf
Android繪制、顯示各個環節均是由VSync驅動,具體來說就是App的每一幀的繪制是從收到VSync信號(VSync-app)開始的,SurfaceFlinger合成當前圖層也是從收到VSync信號(VSync-sf)開始的。為了避免浪費,VSync的分發是按需的,即只有用戶需要(requestNextVsync)的時候,DisplayVSync才會給它發送VSync。
Vsync相關類簡介
首先來介紹一些vsync相關的類,基本上所有vsync相關方法,都是實現在這三個類當中的(以下代碼均為Anrdoid T版本源碼)。
VsyncTracker:其實際上是創建了一個VSyncPredictor對象,這個對象的作用是基于之前的VSync信號時間戳來預測未來VSync時間戳。也就是基于HWVsync來訓練Vsync模型。從而能夠在HWVsync關閉的情況下依然能夠預測未來的VSync時間。
VsyncDispatcher:顧名思義,這個類是用來分發Vsync信號的。實際上最終創建了一個VSyncDispatchTimerQueue對象,負責分發vsync callback事件,需要接收Vsync事件的模塊可以通過registerCallback向其中注冊回調,當有Vsync事件發生時就會遍歷已注冊的回調分發Vsync。
VSyncController:最終方法的實現是在一個VSyncReactor對象中,從代碼中看,這個對象的主要作用是負責傳遞HWVsync,presentFence信號。
sf申請vsync
當sf需要請求刷新時,會調用MessageQueue中的scheduleFrame函數
進而直接調用到VSyncCallbackRegistration中的schedule函數,進一步再到VSyncDispatchTimerQueue中的schedule函數。
這其中rearmTimerSkippingUpdateFor是一個比較關鍵的函數,這個函數會拿到下次觸發vsync的時間戳,并通過setTimer函數向定時器設置這個時間戳,等到定時器被喚醒時,觸發callback以發送vsync。
下面我們來看callback是怎么被層層觸發的。
當定時器到來時,首先回調的是VSyncDispatchTimerQueue中的timerCallback函數
它持有的結構體Invocation中持有一個VSyncDispatchTimerQueueEntry對象,進一步追下去,可以知道這個mCallback最終調到的是MessageQueue中的VsyncCallback函數。
最后的這個紅框的部分,就是我們通常在trace里看到的vsync-sf跳變的地方啦!
app申請vsync
相比于sf的申請,app的申請就顯得要復雜一些。app通常是通過調用requestNextVsync這個binder接口來進行vsync的申請。
這個接口會調用到eventthread中的requestNextVsync函數,此函數會通過mCondition發送廣播。
當threadMain監聽到廣播后,便會繼續執行循環。
eventThread會執行什么呢,關鍵性的函數就是dispSyncSource中的setVSyncEnabled函數,當傳入參數為true時,會調用到CallbackRepeater中的start函數。
繼續往下看,會調用到VSyncCallbackRegistration中的Schedule函數,進一步到VSyncDispatchTimerQueue中的schedule函數。
下面的流程和sf申請vsync基本就是大同小異了,它回調的地方是這里
調用CallbackRepeater中的callback;
最終調用到DispSyncSource中的onVsyncCallback,這也就是我們在trace中看到的vsync-app跳變的地方啦。
相比于vsync-sf,vsync-app還多了一個向申請方發送vsync的過程。繼續往下看,調用到了EventThread中的onVSyncEvent,其會把VsyncEvent保存到mPendingEvents中。
那么這些event在哪里分發呢?答案是還在threadMain中,這個dispatchEvent函數就是用來負責向每個consumer分發vsync的。
說到這里,大家肯定會有一個疑問,為什么vsync-app和vsync-sf都是由同一個定時器觸發的,但是最終回調的位置確不一樣呢?
答案是,這兩種vsync本身注冊回調的位置就不一樣。
vsync-sf是在messagequeue中注冊的
而vsync-app是在callbackRepeater中注冊的。
這也是google在Android T上才做出來的改動,究其原因,應該是谷歌認為應該簡化vsync-sf在內部的傳遞流程,反正也是只給sf自己用的。
-
Android
+關注
關注
12文章
3973瀏覽量
130218 -
定時器
+關注
關注
23文章
3298瀏覽量
118871 -
函數
+關注
關注
3文章
4379瀏覽量
64843
發布評論請先 登錄
DLPC7541是如何設定TSTP輸出Vsync訊號?
【Raspberry Pi 3申請】andriod系統中開發APP
中智訊系列培訓課程:Andriod事件、數據、網絡
如何駕駛所有五個R,G,B,HSYNC和VSYNC?
logcat如何查看Andriod log系統日志?
VSYNC、HSYNC、DOTCLOCK是如何計算的?
區塊鏈分發平臺Huobi Info公測版已正式上線
簡述Vsync信號和View繪制流程之間的關系
VSync的起源是什么

Andriod中Vsync的背景

VSync的虛擬化與同步

VSync offset定義的方法

評論