時間真的是很巧,本來沒打算寫Surface系統的(相比AudioFlinger來說,Surface變化之後的難度真的是毛毛雨了),但為了慶祝泷澤蘿拉發第二部大作,我決定還是要堅持一下。
下面將延續Audio的分析風格(http://www.linuxidc.com/Linux/2012-07/65572.htm),從幾個層面來介紹Surface系統的變化(JB號稱在Surface這塊做過大量的優質的改進,無非就是引入在PC機上早都爛熟的VSYNC,Triple Buffering。但是JB,您能確保這套機制在單核機器上跑得開麼?Win Phone 單核,都比多核Android機器流暢。恐怕還是Android上層Display架構有問題吧??!)
同Audio一樣,想真正理解Surface系統工作原理,最好了解它的演化歷史。
《深入理解Android 卷I》第8章已經把2.2的Surface系統從上到下都撸過一遍了。那幫整天吵嚷著因為大片裡邊有馬賽克而不爽的屌絲們,你們是否把書裡因為不懂而產生的”馬賽克“搞清楚了??
一 Surface工作流程
先說一下Surface的工作流程(只在Native層):
- Java層Surface的創建將導致JNI的Surface_init函數的調用。這個Surface還不是APP使用的Surface,中間會經歷過乾坤大挪移的過程,請參考上面所提的書籍,寫得非常詳細。
- Surface_writeToParcel,將Surface傳遞到APP所在進程去使用。
- APP所在進程通過Surface_readFromParcel,還原一個Surface對象。此時,你的APP就有臉了。
- APP調用Surface_lockCanvas獲得一塊畫布,APP然後在這塊畫布上作畫。
- APP調用Surface_unlockCanvasAndPost,將數據推向SurfaceFlinger,完成此次作畫。
上面這個流程,在JB中,是沒有變化的。從2.2一直到4.1,都是這個流程。
這塊流程變化基本沒有,大家可以直接殺進去看看。
二 SurfaceFlinger變化說明
3.1 SF成員變化說明
SF變化很大,主要是它的兄弟們變化較大。我們分別來說,先看圖1。
圖1 DisplayHardware和兄弟們
圖1的簡單說明如下:
-
JB為了支持VSYNC,修改了DisplayHardware和HardwareComposer(這個鬼類,其實是3.0出現的,)。簡單來說,VSYNC就是一個同步事件。同步嘛,都是到這個點了,大家把狀態對一下。就好像美國大片那些特工們,干某些事情前總要晃晃手表,對下時間一樣。至於拿到這個同步事件後到底去干什麼,以後看代碼就知道了。
-
VSYNC原則上顯示芯片(以後簡稱顯卡)提供的。但JB走得太快了,很多硬件或者沒支持,或者接口上沒支持。所以,不能保證每台JB手機都有來自硬件的VSYNC事件。咋整?終於,JB干出了一個VSyncThread,它是一個線程,用來定時回調以模擬硬件VSYNC事件(這個時間必須比較准確,所以線程優先級必須比較高)。看,這又是一個鐵證,說明JB不適合在單核CPU上跑(我覺得雙核也可能不太適合)。
-
為了支持硬件VSYNC事件,HardwareComposer也增加了相應接口。
-
DisplayHardware同時從DisplayHardwareBase和HardwareComposer的內部類EventHandler派生。從EventHandler派生無非是想基礎它的onVsyncReceived函數。這個函數將在到VSYNC事件時被調用。
-
由於層層的封裝(就和國內工程層層轉包一樣),DisplayHardware內部又定義了一個VsyncHandler虛類,希望人家去繼承它的onVsyncReceived函數。由於使用DH的是SF,所以,大家可大膽猜測這個onVsyncReceived會由SF這一層去處理了。如果去看代碼的話,屌絲們會發現DisplayHardware實現的onVsyncReceived函數其實沒干什麼有毛意義的事情,就是去調用某個實現了VsyncHandler對象的onVsyncReceived函數。(有點繞口令吧?再仔細看看!)
再來看圖2:
圖2 SF和它的兄弟們
圖2解釋如下:
-
先看左上部分。對,你沒看錯。這裡也有MessageHandler,Looper,MessageBase。這以前僅是Java層的東西(所以說,原理是相通的,語言只是工具,如果你懂Java層Message相關的知識,這裡又有神馬理由說不懂呢?除非你沒真正理解Java層Message的東西,參考這篇文章 http://www.linuxidc.com/Linux/2012-07/64095.htm )。注意其中的MessageBase,它是一個虛類,一方面它實現了父類的handleMessage函數,另一方面需要子類實現handle函數。這一點和Java層的Message不一樣。所以,當你在SF中發現有地方往MessageQueue拋消息的時候,就不要去找Handler了,先直接看看這個消息的handle函數!
-
SF保存了一個MessageQueue對象,作為顯示的服務端,它也采取了消息隊列的方式來驅動自己工作。這種方式在4.0中已經這麼做了,但還不夠完全,不夠徹底。JB中,SF的threadLoop函數就一句話:waitForEvent()。對於這種改變,我只能說:很好,很強大!
-
SF保存了一個EventThread對象,這又是一個線程類,它從VsyncHandler派生,實現了onVsyncReceived函數。
-
SF新增IDisplayEventConnection跨binder接口,數據通道是BitTube(MD,Tube的意思就是pipe。無語了。開發SF的人一定和開發AF的人坐得很遠很遠..)。這個類的作用就是收集底層的VSYNC事件,然後派發給各個Connection。大膽猜測下,是不是有些APP所需要的FPS不同,所以需要先由DisplayHardware提供一個最小單位的VSYNC時間,然後再由EventThread根據應用申請的VSYNC時間去觸發。類似時鐘分頻嘛!
大膽猜測,小心求證。恩,希望你們掌握這個方法。