小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

android triple buffer

 昵稱3554661 2017-01-19

轉(zhuǎn)自:http://blog.csdn.NET/yangwen123/article/details/16344375

也可參考:http://djt.qq.com/article/view/987


進(jìn)程間通訊機(jī)制

    Android應(yīng)用程序?yàn)榱四軌驅(qū)⒆约旱腢I繪制在系統(tǒng)的幀緩沖區(qū)上,它們就必須要與SurfaceFlinger服務(wù)進(jìn)行通信,如圖所示:

Android應(yīng)用程序與SurfaceFlinger服務(wù)是運(yùn)行在不同的進(jìn)程中的,因此,它們采用某種進(jìn)程間通信機(jī)制來進(jìn)行通信。由于Android應(yīng)用程序在通知SurfaceFlinger服務(wù)來繪制自己的UI的時(shí)候,需要將UI數(shù)據(jù)傳遞給SurfaceFlinger服務(wù),例如,要繪制UI的區(qū)域、位置等信息。一個(gè)Android應(yīng)用程序可能會有很多個(gè)窗口,而每一個(gè)窗口都有自己的UI數(shù)據(jù),因此,Android系統(tǒng)的匿名共享內(nèi)存機(jī)制就派上用場了。

每一個(gè)Android應(yīng)用程序與SurfaceFlinger服務(wù)之間,都會通過一塊匿名共享內(nèi)存來傳遞UI數(shù)據(jù),如下所示:

 

 

但是單純的匿名共享內(nèi)存在傳遞多個(gè)窗口數(shù)據(jù)時(shí)缺乏有效的管理,所以匿名共享內(nèi)存就被抽象為一個(gè)更上流的數(shù)據(jù)結(jié)構(gòu)SharedClient,如下圖所示:

 

在每個(gè)SharedClient中,最多有31個(gè)SharedBufferStack,每個(gè)SharedBufferStack都對應(yīng)一個(gè)Surface,即一個(gè)窗口。這樣,我們就可以知道為什么每一個(gè)SharedClient里面包含的是一系列SharedBufferStack而不是單個(gè)SharedBufferStack:一個(gè)SharedClient對應(yīng)一個(gè)Android應(yīng)用程序,而一個(gè)Android應(yīng)用程序可能包含有多個(gè)窗口,即Surface。從這里也可以看出,一個(gè)Android應(yīng)用程序至多可以包含31個(gè)窗口。

每個(gè)SharedBufferStack中又包含了N個(gè)緩沖區(qū)(<4.1 N=2; >=4.1 N=3),即顯示刷新機(jī)制中即將提到的雙緩沖和三重緩沖技術(shù)。

顯示刷新機(jī)制

    一般我們在繪制UI的時(shí)候,都會采用一種稱為“雙緩沖”的技術(shù)。雙緩沖意味著要使用兩個(gè)緩沖區(qū)(SharedBufferStack中),其中一個(gè)稱為Front Buffer,另外一個(gè)稱為Back Buffer。UI總是先在Back Buffer中繪制,然后再和Front Buffer交換,渲染到顯示設(shè)備中。理想情況下,這樣一個(gè)刷新會在16ms內(nèi)完成(60FPS),下圖就是描述的這樣一個(gè)刷新過程(Display處理前Front Buffer,CPU、GPU處理Back Buffer。


隨著時(shí)間的推移,Android OS系統(tǒng)一直在不斷完善。但直到Android 4.0問世,有關(guān)UI顯示不流暢的問題也一直未得到根本解決。在整個(gè)進(jìn)化過程中,Android在顯示系統(tǒng)這塊也下了不少功夫,例如,使用硬件加速等技術(shù),但本質(zhì)原因似乎和硬件關(guān)系并不大,因?yàn)閕Phone的硬件配置并不比那些價(jià)格相近的Android機(jī)器的硬件配置強(qiáng),而iPhone UI的流暢性強(qiáng)卻是有目共睹的。從Android 4.1(版本代號為Jelly Bean)開始,Android OS開發(fā)團(tuán)隊(duì)便力圖在每個(gè)版本中解決一個(gè)重要問題。作為嚴(yán)重影響Android口碑問題之一的UI流暢性差的問題,首先在Android 4.1版本中得到了有效處理。其解決方法就是本文要介紹的Project Butter。Project Butter對Android Display系統(tǒng)進(jìn)行了重構(gòu),引入了三個(gè)核心元素,即VSYNC、Triple Buffer和Choreographer。其中,VSYNC是理解Project Buffer的核心。VSYNC是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上已經(jīng)很早就廣泛使用的技術(shù)。讀者可簡單的把它認(rèn)為是一種定時(shí)中斷。接下來,本文將圍繞VSYNC來介紹Android Display系統(tǒng)的工作方式。

Android系統(tǒng)UI交互滯后問題


在一個(gè)典型的顯示系統(tǒng)中,frame buffer代表了屏幕即將要顯示的一幀畫面。假如CPU/GPU繪圖過程與屏幕刷新所使用的buffer是同一塊,那么當(dāng)它們的速度不同步的時(shí)候,是很可能出現(xiàn)類似的畫面“割裂”的。舉個(gè)具體的例子來說,假設(shè)顯示器的刷新率為66Hz,而CPU/GPU繪圖能力則達(dá)到100Hz,也就是它們處理完成一幀數(shù)據(jù)分別需要0.015秒和0.01秒。

0.01秒時(shí),由于兩者速率相差不小,此時(shí)buffer中已經(jīng)準(zhǔn)備好了第1幀數(shù)據(jù),顯示器只顯示了第1幀畫面的2/3
0.015秒時(shí),第1幀畫面完整地顯示出來了,此時(shí)buffer中有1/3的部分已經(jīng)被填充上第2幀數(shù)據(jù)了
0.02秒時(shí),Buffer中已經(jīng)準(zhǔn)備好第2幀數(shù)據(jù),而顯示屏出現(xiàn)了screen tearing,有三分之一是第2幀內(nèi)容,其余的則屬于第1幀畫面

在單緩沖區(qū)的情況下,這個(gè)問題很難規(guī)避。所以引進(jìn)了雙緩沖技術(shù),基本原理就是采用兩塊buffer。一塊back buffer用于CPU/GPU后臺繪制,另一塊framebuffer則用于顯示,當(dāng)back buffer準(zhǔn)備就緒后,它們才進(jìn)行交換。那么什么時(shí)候切換兩個(gè)緩沖區(qū)最合適呢?顯示器有兩個(gè)重要特性,行頻和場頻。行頻(Horizontal ScanningFrequency)又稱為“水平掃描頻率”,是屏幕每秒鐘從左至右掃描的次數(shù); 場頻(Vertical Scanning Frequency)也稱為“垂直掃描頻率”,是每秒鐘整個(gè)屏幕刷新的次數(shù)。由此也可以得出它們的關(guān)系:
行頻=場頻*縱坐標(biāo)分辨率。
當(dāng)掃描完一個(gè)屏幕后,設(shè)備需要重新回到第一行以進(jìn)入下一次的循環(huán),此時(shí)有一段時(shí)間空隙,稱為VerticalBlanking Interval(VBI)。這個(gè)時(shí)間點(diǎn)就是我們進(jìn)行緩沖區(qū)交換的最佳時(shí)間。因?yàn)榇藭r(shí)屏幕沒有在刷新,也就避免了交換過程中出現(xiàn)screentearing的狀況。VSync是VerticalSynchronization的簡寫,它利用VBI時(shí)期出現(xiàn)的vertical sync pulse來保證雙緩沖在最佳時(shí)間點(diǎn)才進(jìn)行交換。在沒有VSync信號同步下的繪圖過程:
沒有VSYNC的繪圖過程

  •  時(shí)間從0開始,進(jìn)入第一個(gè)16ms:Display顯示第0幀,CPU處理完第一幀后,GPU緊接其后處理繼續(xù)第一幀。三者互不干擾,一切正常。
  • 時(shí)間進(jìn)入第二個(gè)16ms:因?yàn)樵缭谏弦粋€(gè)16ms時(shí)間內(nèi),第1幀已經(jīng)由CPU,GPU處理完畢。故Display可以直接顯示第1幀。顯示沒有問題。但在本16ms期間,CPU和GPU卻并未及時(shí)去繪制第2幀數(shù)據(jù)(注意前面的空白區(qū)),而是在本周期快結(jié)束時(shí),CPU/GPU才去處理第2幀數(shù)據(jù)。
  • 時(shí)間進(jìn)入第3個(gè)16ms,此時(shí)Display應(yīng)該顯示第2幀數(shù)據(jù),但由于CPU和GPU還沒有處理完第2幀數(shù)據(jù),故Display只能繼續(xù)顯示第一幀的數(shù)據(jù),結(jié)果使得第1幀多畫了一次(對應(yīng)時(shí)間段上標(biāo)注了一個(gè)Jank)。
  • 通過上述分析可知,此處發(fā)生Jank的關(guān)鍵問題在于,為何第1個(gè)16ms段內(nèi),CPU/GPU沒有及時(shí)處理第2幀數(shù)據(jù)?原因很簡單,CPU可能是在忙別的事情(比如某個(gè)應(yīng)用通過sleep固定時(shí)間來實(shí)現(xiàn)動畫的逐幀顯示),不知道該到處理UI繪制的時(shí)間了。可CPU一旦想起來要去處理第2幀數(shù)據(jù),時(shí)間又錯(cuò)過了!

為解決這個(gè)問題,從Android 4.1Jelly Bean開始,Project Buffer引入了VSYNC,系統(tǒng)在收到VSync pulse后,將馬上開始下一幀的渲染。結(jié)果如下圖所示:

引入VSYNC的繪制過程

每收到VSYNC中斷,CPU就開始處理各幀數(shù)據(jù)。大部分的Android顯示設(shè)備刷新率是60Hz,這也就意味著每一幀最多只能有1/60=16ms左右的準(zhǔn)備時(shí)間。假如CPU/GPU的FPS(FramesPer Second)高于這個(gè)值,那么顯示效果將很好。但是,這時(shí)出現(xiàn)一個(gè)新問題:CPU和GPU處理數(shù)據(jù)的速度都能在16ms內(nèi)完成,而且還有時(shí)間空余,但必須等到VSYNC信號到來后才處理下一幀數(shù)據(jù),因此CPU/GPU的FPS被拉低到與Display的FPS相同。下圖是采用雙緩沖區(qū)的顯示效果:

雙緩沖下CPU/GPU FPS大于刷新頻率

同時(shí)采用了雙緩沖技術(shù)以及VSYNC,可以看到整個(gè)過程還是相當(dāng)不錯(cuò)的,雖然CPU/GPU處理所用的時(shí)間時(shí)短時(shí)長,但總的來說都在16ms以內(nèi),因而不影響顯示效果。A和B分別代表兩個(gè)緩沖區(qū),它們不斷地交換來正確顯示畫面。如果CPU/GPU的FPS小于Display的FPS,會是什么情況呢?


雙緩沖下CPU/GPU FPS小于刷新頻率

當(dāng)CPU/GPU的處理時(shí)間超過16ms時(shí),第一個(gè)VSync到來時(shí),緩沖區(qū)B中的數(shù)據(jù)還沒有準(zhǔn)備好,于是只能繼續(xù)顯示之前A緩沖區(qū)中的內(nèi)容。而B完成后,又因?yàn)槿狈Sync信號,CPU/GPU只能等待下一個(gè)VSync的來臨才開處理下一幀數(shù)據(jù)。于是在這一過程中,有一大段時(shí)間是被浪費(fèi)。當(dāng)下一個(gè)VSync出現(xiàn)時(shí),CPU/GPU馬上執(zhí)行操作,此時(shí)它可操作的buffer是A,相應(yīng)的顯示屏對應(yīng)的就是B。這時(shí)看起來就是正常的。只不過由于執(zhí)行時(shí)間仍然超過16ms,導(dǎo)致下一次應(yīng)該執(zhí)行的緩沖區(qū)交換又被推遲了。也就是說在第二個(gè)16ms時(shí)間段,Display本應(yīng)顯示B幀,但卻因?yàn)镚PU還在處理B幀,導(dǎo)致A幀被重復(fù)顯示,同時(shí)CPU無所事事,因?yàn)锳 被Display在使用。B被GPU在使用。為什么CPU不能在第二個(gè)16ms處即VSync到來就開始工作呢?原因就是只有兩個(gè)Buffer。如果有第三個(gè)Buffer的存在,CPU就可以開始工作,而不至于空閑。出于這一思路就引出了Triple Buffer。結(jié)果如圖所示:


Triple Buffering

第二個(gè)16ms時(shí)間段,CPU使用C Buffer繪圖。雖然剛開始還是會多顯示A幀一次,但后續(xù)顯示效果就比較好,第三個(gè)VSync信號到來時(shí),由于GPU/CPU都處理完了B,因此B被顯示,在第四個(gè)VSync信號到來時(shí),GPU/CPU同時(shí)完成了A和C,并著手開始處理B,此時(shí)C被顯示。從上圖可以看出,CPU繪制的第C幀數(shù)據(jù)要到第四個(gè)16ms才能顯示,這比雙Buffer情況多了16ms延遲。我們知道,應(yīng)用程序這邊的本地窗口Surface在SurfaceFlinger服務(wù)進(jìn)程端有一個(gè)對應(yīng)的BufferQueue對象,該對象用于管理Surface的圖形繪制緩沖區(qū)。BufferQueue中最多有32個(gè)BufferSlot,不過在實(shí)際使用時(shí)具體值是可以設(shè)置的。在Layer對象的onFirstRef函數(shù)中初始化了圖形緩沖區(qū)的個(gè)數(shù):
  1. #ifdef TARGET_DISABLE_TRIPLE_BUFFERING  
  2. #warning "disabling triple buffering"  
  3.     mSurfaceTexture->setBufferCountServer(2);  
  4. #else  
  5.     mSurfaceTexture->setBufferCountServer(3);  
  6. #endif  

Project Buffer分析


Project Buffer的三個(gè)關(guān)鍵點(diǎn):
1. 需要VSYNC定時(shí)中斷;
2. 當(dāng)雙Buffer不夠使用時(shí),該系統(tǒng)可分配第三塊Buffer;
3. 圖形buffer的繪制工作又VSYNC信號觸發(fā);


  • HardwareComposer封裝了相關(guān)的HAL層,如果硬件廠商提供的HAL層實(shí)現(xiàn)能定時(shí)產(chǎn)生VSYNC中斷,則直接使用硬件的VSYNC中斷,否則HardwareComposer內(nèi)部會通過VSyncThread來模擬產(chǎn)生VSYNC中斷(其實(shí)現(xiàn)很簡單,就是sleep固定時(shí)間,然后喚醒)。
  • 當(dāng)VSYNC中斷產(chǎn)生時(shí)(不管是硬件產(chǎn)生還是VSyncThread模擬的),VSyncHandler的onVSyncReceived函數(shù)將被調(diào)用。所以,對VSYNC中斷來說,VSyncHandler的onVSyncReceived,就是其中斷處理函數(shù)。
VSyncHandler的實(shí)例是EventThread。下邊是EventThread類的聲明:

  1. class EventThread : public Thread, public DisplayHardware::VSyncHandler  
EventThread本身運(yùn)行在一個(gè)單獨(dú)的線程中,并繼承了VSyncHandler。EventThread在其線程函數(shù)threadLoop中等待下一次VSYNC的到來,并派發(fā)該中斷事件給VSYNC監(jiān)聽者。通過EventThread,VSYNC中斷事件可派發(fā)給多個(gè)該中斷的監(jiān)聽者去處理。


IDisplayEventConnection是一個(gè)純虛類,它代表VSYNC中斷的監(jiān)聽者。其實(shí)體類是EventThread的內(nèi)部類Connection。IDisplayEventConnection定義了一個(gè)getDataChannel函數(shù),該函數(shù)返回一個(gè)BitTube實(shí)例,其內(nèi)部實(shí)現(xiàn)為socketpair。這個(gè)實(shí)例提供的read/write方法,用于傳送具體的信號數(shù)據(jù)。EventThread最重要的一個(gè)VSYNC監(jiān)聽者就是MessageQueue的mEvents對象,來自EventThread的VSYNC中斷信號,將通過MessageQueue轉(zhuǎn)化為一個(gè)REFRESH消息并傳遞給SurfaceFlinger的onMessageReceived函數(shù)處理。DisplayEventReceiver是一個(gè)abstract class,其JNI的代碼部分會創(chuàng)建一個(gè)IDisplayEventConnection的VSYNC監(jiān)聽者對象。這樣,來自EventThread的VSYNC中斷信號就可以傳遞給Choreographer對象了。當(dāng)Choreographer收到VSYNC信號時(shí),就會調(diào)用使用者通過postCallback設(shè)置的回調(diào)函數(shù)。



  Project Buffer分析

上一節(jié)對VSYNC進(jìn)行了理論分析,其實(shí)也引出了Project Buffer的三個(gè)關(guān)鍵點(diǎn):

  • 核心關(guān)鍵:需要VSYNC定時(shí)中斷。
  • Triple Buffer:當(dāng)雙Buffer不夠使用時(shí),該系統(tǒng)可分配第三塊Buffer。
  • 另外,還有一個(gè)非常隱秘的關(guān)鍵點(diǎn):即將繪制工作都統(tǒng)一到VSYNC時(shí)間點(diǎn)上。這就是Choreographer的作用。Choreographer是一個(gè)極富詩意的詞,意為舞蹈編導(dǎo)。在它的統(tǒng)一指揮下,應(yīng)用的繪制工作都將變得井井有條。

下面來看Project Buffer實(shí)現(xiàn)的細(xì)節(jié)。

2.1  SurfaceFlinger家族的改進(jìn)

首先被動刀的是SurfaceFlinger家族成員。目標(biāo)是提供VSYNC中斷。相關(guān)類圖如圖5所示:

5  SurfaceFlinger中和VSYNC有關(guān)的類

由圖5可知:

  • HardwareComposer封裝了相關(guān)的HAL層,如果硬件廠商提供的HAL層實(shí)現(xiàn)能定時(shí)產(chǎn)生VSYNC中斷,則直接使用硬件的VSYNC中斷,否則HardwareComposer內(nèi)部會通過VSyncThread來模擬產(chǎn)生VSYNC中斷(其實(shí)現(xiàn)很簡單,就是sleep固定時(shí)間,然后喚醒)。
  • 當(dāng)VSYNC中斷產(chǎn)生時(shí)(不管是硬件產(chǎn)生還是VSyncThread模擬的),VSyncHandleronVSyncReceived函數(shù)將被調(diào)用。所以,對VSYNC中斷來說,VSyncHandleronVSyncReceived,就是其中斷處理函數(shù)。

SurfaceFlinger家族中,VSyncHandler的實(shí)例是EventThread。下邊是EventThread類的聲明:

class EventThread : public Thread, public DisplayHardware::VSyncHandler

EventThread定義可知,它本身運(yùn)行在一個(gè)單獨(dú)的線程中,并繼承了VSyncHandlerEventThread的核心處理在其線程函數(shù)threadLoop中完成,其處理邏輯主要是:

  • 等待下一次VSYNC的到來,并派發(fā)該中斷事件給VSYNC監(jiān)聽者。

通過EventThread,VSYNC中斷事件可派發(fā)給多個(gè)該中斷的監(jiān)聽者去處理。相關(guān)類如圖6所示:

6  EventThreadVSYNC中斷監(jiān)聽者

由圖6可知:

  • SurfaceFlingerThread派生,其核心功能單獨(dú)運(yùn)行在一個(gè)線程中。
  • SurfaceFlinger包括一個(gè)EventThread和一個(gè)MessageQueue對象。
  • 對象通過mEvents成員指向一個(gè)IDisplayEventConnection類型的對象。IDisplayEventConnection是一個(gè)純虛類,它代表VSYNC中斷的監(jiān)聽者。其實(shí)體類是EventThread的內(nèi)部類Connection。
  • IDisplayEventConnection定義了一個(gè)getDataChannel函數(shù),該函數(shù)返回一個(gè)BitTube實(shí)例。這個(gè)實(shí)例提供的read/write方法,用于傳送具體的信號數(shù)據(jù)(其內(nèi)部實(shí)現(xiàn)為socketpair,可通過Binder實(shí)現(xiàn)進(jìn)程跨越)。

EventThread最重要的一個(gè)VSYNC監(jiān)聽者就是MessageQueuemEvents對象。當(dāng)然,這一切都是為最大的后臺老板SurfaceFlinger服務(wù)的。來自EventThreadVSYNC中斷信號,將通過MessageQueue轉(zhuǎn)化為一個(gè)REFRESH消息并傳遞給SurfaceFlingeronMessageReceived函數(shù)處理。

有必要指出,4.1SurfaceFlinger onMessageReceived函數(shù)的實(shí)現(xiàn)僅僅是將4.0版本的SurfaceFlinger的核心函數(shù)挪過來罷了[②],并未做什么改動。

以上是Project BufferSurfaceFlinger所做的一些改動。那么Triple Buffer是怎么處理的呢?幸好從Android 2.2開始,DisplayPage Flip算法就不依賴Buffer的個(gè)數(shù),Buffer個(gè)數(shù)不過是算法的一個(gè)參數(shù)罷了。所以,Triple Buffer的引入,只是把Buffer的數(shù)目改成了3,而算法本身相對于4.0來說并沒有變化。圖7Triple Buffer的設(shè)置示意圖:

7  Layer.cpp中對Triple Buffer的設(shè)置

7所示,為Layer.cpp中對Buffer個(gè)數(shù)的設(shè)置。TARGET_DISABLE_TRIPLE_BUFFERING宏可設(shè)置Buffer的個(gè)數(shù)。對某些內(nèi)存/顯存并不是很大的設(shè)備,也可以選擇不使用Triple Buffer。

2.2  Choreographer介紹

Choreographer是一個(gè)Java類。第一次看到這個(gè)詞時(shí),我很激動。一個(gè)小小的命名真的反應(yīng)出了設(shè)計(jì)者除coding之外的廣博的視界。試想,如果不是對舞蹈有相當(dāng)了解或喜愛,一般人很難想到用這個(gè)詞來描述它。

Choreographer的定義和基本結(jié)構(gòu)如圖8所示:

8  Choreographer的定義和結(jié)構(gòu)

8中:

  • Choreographer是線程單例的,而且必須要和一個(gè)Looper綁定,因?yàn)槠鋬?nèi)部有一個(gè)Handler需要和Looper綁定。
  • DisplayEventReceiver是一個(gè)abstract class,其JNI的代碼部分會創(chuàng)建一個(gè)IDisplayEventConnectionVSYNC監(jiān)聽者對象。這樣,來自EventThreadVSYNC中斷信號就可以傳遞給Choreographer對象了。由圖8可知,當(dāng)VSYNC信號到來時(shí),DisplayEventReceiveronVsync函數(shù)將被調(diào)用。
  • 另外,DisplayEventReceiver還有一個(gè)scheduleVsync函數(shù)。當(dāng)應(yīng)用需要繪制UI時(shí),將首先申請一次VSYNC中斷,然后再在中斷處理的onVsync函數(shù)去進(jìn)行繪制。
  • Choreographer定義了一個(gè)FrameCallback interface,每當(dāng)VSYNC到來時(shí),其doFrame函數(shù)將被調(diào)用。這個(gè)接口對Android Animation的實(shí)現(xiàn)起了很大的幫助作用。以前都是自己控制時(shí)間,現(xiàn)在終于有了固定的時(shí)間中斷。
  • Choreographer的主要功能是,當(dāng)收到VSYNC信號時(shí),去調(diào)用使用者通過postCallback設(shè)置的回調(diào)函數(shù)。目前一共定義了三種類型的回調(diào),它們分別是:
  • CALLBACK_INPUT:優(yōu)先級最高,和輸入事件處理有關(guān)。
  • CALLBACK_ANIMATION:優(yōu)先級其次,和Animation的處理有關(guān)。
  • CALLBACK_TRAVERSAL:優(yōu)先級最低,和UI等控件繪制有關(guān)。

優(yōu)先級高低和處理順序有關(guān)。當(dāng)收到VSYNC中斷時(shí),Choreographer將首先處理INPUT類型的回調(diào),然后是ANIMATION類型,最后才是TRAVERSAL類型。

此外,讀者在自行閱讀Choreographer相關(guān)代碼時(shí),還會發(fā)現(xiàn)AndroidMessage/Looper[③]也進(jìn)行了一番小改造,使之支持Asynchronous MessageSynchronization Barrier(參照Looper.javapostSyncBarrier函數(shù))。其實(shí)現(xiàn)非常巧妙,這部分內(nèi)容就留給讀者自己理解并欣賞了。

相比SurfaceFlinger,ChoreographerAndroid 4.1中的新事物,下面將通過一個(gè)實(shí)例來簡單介紹Choreographer的工作原理。

假如UI中有一個(gè)控件invalidate了,那么它將觸發(fā)ViewRootImplinvalidate函數(shù),該函數(shù)將最終調(diào)用ViewRootImplscheduleTraversals。其代碼如圖9所示:

9  ViewRootImpl scheduleTraversals函數(shù)的實(shí)現(xiàn)

由圖9可知,scheduleTraversals首先禁止了后續(xù)的消息處理功能,這是由設(shè)置LooperpostSyncBarrier來完成的。一旦設(shè)置了SyncBarrier,所有非Asynchronous的消息便將停止派發(fā)。

然后,為Choreographer設(shè)置了CALLBACK類型為TRAVERSAL的處理對象,即mTraversalRunnable。

最后調(diào)用scheduleConsumeBatchedInput,這個(gè)函數(shù)將為Choreographer設(shè)置了CALLBACK類型為INPUT的處理對象。

ChoreographerpostCallback函數(shù)將會申請一次VSYNC中斷(通過調(diào)用DisplayEventReceiverscheduleVsync實(shí)現(xiàn))。當(dāng)VSYNC信號到達(dá)時(shí),Choreographer doFrame函數(shù)被調(diào)用,內(nèi)部代碼會觸發(fā)回調(diào)處理。代碼片段如圖10所示:

10  Choreographer doFrame函數(shù)片段

ViewRootImpl來說,其TRAVERSAL回調(diào)對應(yīng)的處理對象,就是前面介紹的mTraversalRunnable,它的代碼很簡單,如圖11所示:

11  mTraversalRunnable的實(shí)現(xiàn)

doTraversal內(nèi)部實(shí)現(xiàn)和Android 4.0版本一致。故相比于4.0來說,4.1只是把doTraversal調(diào)用位置放到VSYNC中斷處理中了。

通過上邊的介紹,可知Choreographer確實(shí)做到了對繪制工作的統(tǒng)一安排,不愧是個(gè)長于統(tǒng)籌安排的“舞蹈編導(dǎo)”。

三總結(jié)

本文通過對Android Project Butter的分析,向讀者介紹了VSYNC原理以及Android Display系統(tǒng)的實(shí)現(xiàn)。除了VSYNC外,Project Butter還包括其他一些細(xì)節(jié)的改進(jìn),例如避免重疊區(qū)域的繪制等。

簡言之,Project Butter從本質(zhì)上解決了Android UI不流暢的問題,而且從Google I/O給出的視頻來看,其效果相當(dāng)不錯(cuò)。但實(shí)際上它對硬件配置還是有一定要求的。因?yàn)?span style="font-family:'Times New Roman'">VSYNC中斷處理的線程優(yōu)先級一定要高,否則EventThread接收到VSYNC中斷,卻不能及時(shí)去處理,那就喪失同步的意義了。所以,筆者估計(jì)目前將有一大批單核甚至雙核機(jī)器無法嘗到Jelly Bean了。



    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多