Android 4.1 Surface系統變化說明

來源:互聯網
上載者:User
時間真的是很巧,本來沒打算寫Surface系統的(相比AudioFlinger來說,Surface變化之後的難度真的是毛毛雨了),但為了慶祝瀧澤蘿拉發第二部大作,我決定還是要堅持一下。下面將延續Audio的分析風格,從幾個層面來介紹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(不懂的同學們,參考這篇文章http://blog.sina.com.cn/s/blog_4a3946360100wjoo.html),修改了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://blog.csdn.net/innost/article/details/6055793)。注意其中的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時間去觸發。類似時鐘分頻嘛!
大膽猜測,小心求證。恩,希望你們掌握這個方法。 3.2 createSurface變化說明從流程上說,這個函數並沒有變化,有變化的還是那幾個兄弟。見圖3,這裡只討論NormalSurface的情況:

圖3 Layer和SurfaceTexture的關係稍加解釋:
  • 圖3左邊三個是Layer的派生關係。Layer是什嗎?Layer是SF中代表每個顯示層的東西,裡邊處理了繪畫等眾多邏輯。
  • 右邊是ISurfaceTexture。它其實是Android Native顯示層的介面,其作用類似AudioTrack和AudioRecord。以後偶會給一個例子,就是直接使用ISurfaceTexture API繪畫的。相比其他版本,JB在SurfaceTexure這一塊又抽象出了BufferQueue一層。我個人覺得是越搞越複雜了。BufferQueue,再處理PageFlip的時候,可能有些好處吧。
  • 用戶端調用getSurfaceTexture的時候,在Layer的createSurface中,將返回SurfaceTextureLayer給用戶端。用戶端然後調用requestBuffer,queueBuffer,dequeueBuffer擷取GraphicBuffer(簡單認為為顯存吧)。
  • ISurfaceTexture內部定義了兩個POD結構體,QueueBufferInput/Output,POD結構體,其實就是一個沒有什麼static成員的struct。這兩個結構體內部包含一些諸如寬度,高度,時間戳記方面的資訊,將做為queueBuffer函數的參數傳遞。具體作用,沒細看。
折騰來,折騰去,無非是搞得更複雜了.....要是能看到相關設計文檔就好了....夠我們學一陣子了。  3.3 dequeueBuffer和queueBuffer變化說明
  • dequeueBuffer:取空閑顯卡記憶體,以給app作畫。如果編譯的時候開啟了TARGET_DISABLE_TRIPLE_BUFFERING,則顯卡記憶體預設是2塊,否則是3塊。相關queue/dequeue操作的代碼,早在2.2的時候就不是僅支援2塊的。也就是說,代碼裡邊其實是可以支援3,4,5等等。不就是一個數組來回倒騰麼,當然不會蠢到寫死為2!這部分邏輯相比ICS,沒有太大的變化。只是把代碼挪到BufferQueue裡邊來了。
下面來看看圖4,即queueBuffer函數的流程圖。這部分變化比較大。

 圖4 queueBuffer的流程 整個這麼複雜的流程,其實從第4步開始,基本上都是一個簡單的回調。這就是層次太多帶來的負面作用。根據圖1,最後調用的是EventThread的requestNextSync,這個函數巨簡單,就是觸發一個同步廣播對象.....還有很多知識點,但不能放在這一節裡扯了。下面,我們來看SurfaceFlinger和EventThread的關係。  3.4 SurfaceFlinger和EventThread的工作流程說明上一節,有個地方沒法說明的就是EventThread到底是幹嘛的,它和SF分別是兩個線程(MD,又是多線程編程,同步很重要啊!)在SF的readyToRun函數中,將通過MesssageQueue的setEventThread函數建立SF和ET的關係。看看代碼吧:void MessageQueue::setEventThread(const sp<EventThread>& eventThread){ mEventThread = eventThread; mEvents = eventThread->createEventConnection(); mEventTube = mEvents->getDataChannel(); mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT, MessageQueue::cb_eventReceiver, this);}也就是說,當EventThread有什麼鳥事的時候,都會通過cb_eventReceiver回調到SF線程。注意:JB以前,Android老是喜歡用pipe作為處理序間通訊的手段,現在改成socketpair了。這是一個很大的變化。所以,會網路編程的同學可以happy一下了。不會的淫,也無所謂,反正是把socket當pipe來使,都是IPC通訊手段,你管它用得是什麼呢!EventThread的requestSync被調用後,會觸發EventThread的線程通過Connection發送一個訊息給SF所在的線程,即剛才那個cb_eventReceiver被調用,圖4是此後的工作流程。(SF系統現在變得也是磨磨唧唧了,不懂POSIX編程屌絲們,你們無論如何得花點功夫研究了。)

圖5 SF工作流程正5最後的第10,11步,終於看到了熟悉的handlePageFlip。FT,相比ICS的版本,函數是越調越多,層次越來越複雜。到時候別搞得和Java Framework一樣,那效率就.....  四總結相比AF來說,SF主要是層次增加,函數調用繞來繞去。另外,新增了IDisplayEventConnection介面,這玩意兒還有待後續研究。今天講得這些東西,應該可以協助大家對JB SF有一個大略的瞭解。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.