App與SurfaceFlinger是不同的進(jìn)程,它們之間傳遞VSync的話涉及到進(jìn)程間通信,而且VSync頻率很高,App很多,所以VSync的分發(fā)效率要很高才行。Linux進(jìn)程間通信方式總共就那么幾種,Android選擇了Domain Socket,應(yīng)該是因?yàn)槠涓咝?、?jiǎn)單、且有序吧,并將其封裝成了更易用的BitTube。
VSync-app/sf
Android繪制、顯示各個(gè)環(huán)節(jié)均是由VSync驅(qū)動(dòng),具體來(lái)說就是App的每一幀的繪制是從收到VSync信號(hào)(VSync-app)開始的,SurfaceFlinger合成當(dāng)前圖層也是從收到VSync信號(hào)(VSync-sf)開始的。為了避免浪費(fèi),VSync的分發(fā)是按需的,即只有用戶需要(requestNextVsync)的時(shí)候,DisplayVSync才會(huì)給它發(fā)送VSync。
Vsync相關(guān)類簡(jiǎn)介
首先來(lái)介紹一些vsync相關(guān)的類,基本上所有vsync相關(guān)方法,都是實(shí)現(xiàn)在這三個(gè)類當(dāng)中的(以下代碼均為Anrdoid T版本源碼)。
VsyncTracker:其實(shí)際上是創(chuàng)建了一個(gè)VSyncPredictor對(duì)象,這個(gè)對(duì)象的作用是基于之前的VSync信號(hào)時(shí)間戳來(lái)預(yù)測(cè)未來(lái)VSync時(shí)間戳。也就是基于HWVsync來(lái)訓(xùn)練Vsync模型。從而能夠在HWVsync關(guān)閉的情況下依然能夠預(yù)測(cè)未來(lái)的VSync時(shí)間。
VsyncDispatcher:顧名思義,這個(gè)類是用來(lái)分發(fā)Vsync信號(hào)的。實(shí)際上最終創(chuàng)建了一個(gè)VSyncDispatchTimerQueue對(duì)象,負(fù)責(zé)分發(fā)vsync callback事件,需要接收Vsync事件的模塊可以通過registerCallback向其中注冊(cè)回調(diào),當(dāng)有Vsync事件發(fā)生時(shí)就會(huì)遍歷已注冊(cè)的回調(diào)分發(fā)Vsync。
VSyncController:最終方法的實(shí)現(xiàn)是在一個(gè)VSyncReactor對(duì)象中,從代碼中看,這個(gè)對(duì)象的主要作用是負(fù)責(zé)傳遞HWVsync,presentFence信號(hào)。
sf申請(qǐng)vsync
當(dāng)sf需要請(qǐng)求刷新時(shí),會(huì)調(diào)用MessageQueue中的scheduleFrame函數(shù)
進(jìn)而直接調(diào)用到VSyncCallbackRegistration中的schedule函數(shù),進(jìn)一步再到VSyncDispatchTimerQueue中的schedule函數(shù)。
這其中rearmTimerSkippingUpdateFor是一個(gè)比較關(guān)鍵的函數(shù),這個(gè)函數(shù)會(huì)拿到下次觸發(fā)vsync的時(shí)間戳,并通過setTimer函數(shù)向定時(shí)器設(shè)置這個(gè)時(shí)間戳,等到定時(shí)器被喚醒時(shí),觸發(fā)callback以發(fā)送vsync。
下面我們來(lái)看callback是怎么被層層觸發(fā)的。
當(dāng)定時(shí)器到來(lái)時(shí),首先回調(diào)的是VSyncDispatchTimerQueue中的timerCallback函數(shù)
它持有的結(jié)構(gòu)體Invocation中持有一個(gè)VSyncDispatchTimerQueueEntry對(duì)象,進(jìn)一步追下去,可以知道這個(gè)mCallback最終調(diào)到的是MessageQueue中的VsyncCallback函數(shù)。
最后的這個(gè)紅框的部分,就是我們通常在trace里看到的vsync-sf跳變的地方啦!
app申請(qǐng)vsync
相比于sf的申請(qǐng),app的申請(qǐng)就顯得要復(fù)雜一些。app通常是通過調(diào)用requestNextVsync這個(gè)binder接口來(lái)進(jìn)行vsync的申請(qǐng)。
這個(gè)接口會(huì)調(diào)用到eventthread中的requestNextVsync函數(shù),此函數(shù)會(huì)通過mCondition發(fā)送廣播。
當(dāng)threadMain監(jiān)聽到廣播后,便會(huì)繼續(xù)執(zhí)行循環(huán)。
eventThread會(huì)執(zhí)行什么呢,關(guān)鍵性的函數(shù)就是dispSyncSource中的setVSyncEnabled函數(shù),當(dāng)傳入參數(shù)為true時(shí),會(huì)調(diào)用到CallbackRepeater中的start函數(shù)。
繼續(xù)往下看,會(huì)調(diào)用到VSyncCallbackRegistration中的Schedule函數(shù),進(jìn)一步到VSyncDispatchTimerQueue中的schedule函數(shù)。
下面的流程和sf申請(qǐng)vsync基本就是大同小異了,它回調(diào)的地方是這里
調(diào)用CallbackRepeater中的callback;
最終調(diào)用到DispSyncSource中的onVsyncCallback,這也就是我們?cè)趖race中看到的vsync-app跳變的地方啦。
相比于vsync-sf,vsync-app還多了一個(gè)向申請(qǐng)方發(fā)送vsync的過程。繼續(xù)往下看,調(diào)用到了EventThread中的onVSyncEvent,其會(huì)把VsyncEvent保存到mPendingEvents中。
那么這些event在哪里分發(fā)呢?答案是還在threadMain中,這個(gè)dispatchEvent函數(shù)就是用來(lái)負(fù)責(zé)向每個(gè)consumer分發(fā)vsync的。
說到這里,大家肯定會(huì)有一個(gè)疑問,為什么vsync-app和vsync-sf都是由同一個(gè)定時(shí)器觸發(fā)的,但是最終回調(diào)的位置確不一樣呢?
答案是,這兩種vsync本身注冊(cè)回調(diào)的位置就不一樣。
vsync-sf是在messagequeue中注冊(cè)的
而vsync-app是在callbackRepeater中注冊(cè)的。
這也是google在Android T上才做出來(lái)的改動(dòng),究其原因,應(yīng)該是谷歌認(rèn)為應(yīng)該簡(jiǎn)化vsync-sf在內(nèi)部的傳遞流程,反正也是只給sf自己用的。
-
Android
+關(guān)注
關(guān)注
12文章
3909瀏覽量
126933 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3228瀏覽量
114192 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4263瀏覽量
62250
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論