天天看點

Android系統Surface機制的SurfaceFlinger服務簡要介紹和學習計劃

前面我們從Android應用程式與SurfaceFlinger服務的關系出發,從側面簡單學習了SurfaceFlinger服務。有了這些預備知識之後,我們就可以從正面來分析SurfaceFlinger服務的實作原理了。SurfaceFlinger服務負責管理系統的幀緩沖區裝置,并且負責渲染系統的UI,即各個應用程式的UI。在本文中,我們就簡要介紹SurfaceFlinger服務,并且制定學習計劃。

      由于SurfaceFlinger服務需要與Android應用程式執行Binder程序間通信,是以,它本身就是一個Binder本地對象,如圖1所示:

圖1 SurfaceFlinger服務的類關系圖

       SurfaceFlinger服務實作的接口為ISurfaceComposer,後者定義在檔案frameworks/base/include/surfaceflinger/ISurfaceComposer.h中,如下所示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

<code>class</code> <code>ISurfaceComposer : </code><code>public</code> <code>IInterface</code>

<code>{</code>

<code>public</code><code>:</code>

<code>    </code><code>DECLARE_META_INTERFACE(SurfaceComposer);</code>

<code>    </code><code>......</code>

<code>    </code><code>/* create connection with surface flinger, requires</code>

<code>     </code><code>* ACCESS_SURFACE_FLINGER permission</code>

<code>     </code><code>*/</code>

<code>    </code><code>virtual sp&lt;ISurfaceComposerClient&gt; createConnection() = 0;</code>

<code>    </code><code>/* create a client connection with surface flinger</code>

<code>    </code><code>virtual sp&lt;ISurfaceComposerClient&gt; createClientConnection() = 0;</code>

<code>    </code><code>/* retrieve the control block */</code>

<code>    </code><code>virtual sp&lt;IMemoryHeap&gt; getCblk() const = 0;</code>

<code>    </code><code>/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */</code>

<code>    </code><code>virtual void openGlobalTransaction() = 0;</code>

<code>    </code><code>virtual void closeGlobalTransaction() = 0;</code>

<code>    </code><code>/* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */</code>

<code>    </code><code>virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0;</code>

<code>    </code><code>virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags) = 0;</code>

<code>    </code><code>/* Set display orientation. requires ACCESS_SURFACE_FLINGER permission */</code>

<code>    </code><code>virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags) = 0;</code>

<code>    </code><code>/* signal that we're done booting.</code>

<code>     </code><code>* Requires ACCESS_SURFACE_FLINGER permission</code>

<code>    </code><code>virtual void bootFinished() = 0;</code>

<code>    </code><code>/* Capture the specified screen. requires READ_FRAME_BUFFER permission</code>

<code>     </code><code>* This function will fail if there is a secure window on screen.</code>

<code>    </code><code>virtual status_t captureScreen(DisplayID dpy,</code>

<code>            </code><code>sp&lt;IMemoryHeap&gt;* heap,</code>

<code>            </code><code>uint32_t* width, uint32_t* height, PixelFormat* format,</code>

<code>            </code><code>uint32_t reqWidth, uint32_t reqHeight) = 0;</code>

<code>    </code><code>virtual status_t turnElectronBeamOff(int32_t mode) = 0;</code>

<code>    </code><code>virtual status_t turnElectronBeamOn(int32_t mode) = 0;</code>

<code>    </code><code>/* Signal surfaceflinger that there might be some work to do</code>

<code>     </code><code>* This is an ASYNCHRONOUS call.</code>

<code>    </code><code>virtual </code><code>void</code> <code>signal() </code><code>const</code> <code>= </code><code>0</code><code>;</code>

<code>};</code>

       ISurfaceComposer接口有13個成員函數,下面我們就簡單介紹一下:

--getCblk:Android應用程式通過它來請求SurfaceFlinger服務傳回一塊匿名共享記憶體,傳回的匿名共享記憶體包含了裝置顯示屏的資訊,例如,寬度和高度資訊。

--openGlobalTransaction:Android應用程式通過它請求SurfaceFlinger服務來增加一個全局Transaction計數,用來批量修改UI屬性資訊。注意,這些被修改的UI屬性資訊會被緩存起來,不會馬上生效。要使得這些被修改的UI屬性資訊生效,需要調用另外一個成員函數closeGlobalTransaction,如下所述。

--closeGlobalTransaction:Android應用程式通過它請求SurfaceFlinger服務來減少一個全局Transaction計數。當這個全局Transaction計數減少至0的時候,前面通過openGlobalTransaction來請求修改的UI屬性資訊就會馬上生效。

--freezeDisplay:Android應用程式通過它來請求SurfaceFlinger服務來當機螢幕。螢幕在被當機期間,所有UI渲染操作都會被緩存起來,等待被執行。

--unfreezeDisplay:Android應用程式通過它來請求SurfaceFlinger服務來解凍螢幕。螢幕被解凍之後,SurfaceFlinger服務就可以執行UI渲染操作了。

--setOrientation:Android應用程式通過它來請求SurfaceFlinger服務裝置螢幕的旋轉方向。

--captureScreen:Android應用程式通過它來請求SurfaceFlinger服務截取螢幕圖像。

--turnElectronBeamOff:Android應用程式通過它來請求SurfaceFlinger服務關閉螢幕。

--turnElectronBeamOn:Android應用程式通過它來請求SurfaceFlinger服務點亮螢幕。

       了解了ISurfaceComposer接口的定義之後,我們再來看SurfaceFlinger服務的Binder代理對象BpSurfaceComposer的實作,如圖2所示:

圖2 SurfaceFlinger服務的Binder代理對象的類關系圖

       Android應用程式獲得了SurfaceFlinger服務的一個Binder代理對象,即一個BpSurfaceComposer對象之後,就可以請求SurfaceFlinger服務來建立以及渲染自己的UI了。

       接下來,我們再簡單介紹一下SurfaceFlinger類的定義,如圖3所示:

圖3 SurfaceFlinger類的定義

       SurfaceFlinger類有兩個類型為State的成員變量mCurrentState和mDrawingState。其中,成員變量mCurrentState用來描述系統下一次要渲染的UI的狀态;而mDrawingState用來描述目前正要渲染的UI的狀态。

       State類用來描述一個UI狀态,它有四個重要的成員變量layersSortedByZ、orientation、orientationType和freezeDisplay。其中,成員變量layersSortedByZ是一個類型為LayerVector的向量,裡面儲存的系統所包含的Surface,每一個Surface使用一個LayerBase對象來描述,并且它們按照 Z軸順序來排列;成員變量orientation和orientationType的類型均為uint8_t,它們用來描述螢幕的方向; 成員變量freezeDisplay的類型也是uint8_t,用來描述螢幕是否處于被當機狀态。

       SurfaceFlinger類的成員變量mVisibleLayerSortedByZ是一個類型為sp&lt;LayerBase&gt;的Vector,它是用來儲存SurfaceFlinger服務下一次要渲染的、處于可見狀态的Surface的,它們是來自SurfaceFlinger類的成員變量mDrawingState所描述的一個State對象的成員變量layersSortedByZ的。

       SurfaceFlinger類的成員變量mGraphicPlanes是一個類型為GraphicPlane的數組,它是用來描述系統所有的顯示裝置的。從這個數組的大小等于1可以知道,目前Android系統隻支援一個顯示裝置。

       GraphicPlane類有四個重要的成員變量mHw、mOrientation、mWidth和mHeight。其中,成員變量mHw指向一個DisplayHardware對象,用來描述一個硬體顯示裝置;成員變量mOrientation、mWidth和mHeight的類型均為int,分别用來描述一個硬體顯示裝置的旋轉方向、寬度和高度。我們可以通過調用GraphicPlane類的成員函數setDisplayHardware和displayHardware來裝置和擷取一個GraphicPlane對象内部所包含的一個硬體顯示裝置。

       DisplayHardware類有一個重要的成員變量mNativeWindow,它是一個類型為FramebufferNativeWindow的強指針。FramebufferNativeWindow類是用來描述一個Android系統本地視窗,而這個視窗代表的是系統的硬體幀緩沖區。DisplayHardware類的成員函數flip是用來渲染系統UI的,即将後端的圖形緩沖區翻轉為前端的圖形緩沖區,并且渲染在硬體幀緩沖區去。

     了解了SurfaceFlinger類的重要成員變量之後,我們再來了解它的幾個重要成員函數threadLoop、waitForEvent、signalEvent、handleConsoleEvents、handleTransaction、handlePageFlip、handleRepaint和postFramebuffer。

      SurfaceFlinger服務雖然是在System程序中啟動的,但是它在啟動的時候建立一個線程來專門負責渲染UI。為了友善描述,我們将這個線程稱為UI渲染線程。UI渲染線程的執行函數就為SurfaceFlinger類的成員函數threadLoop,同時它有一個消息隊列。當UI渲染線程不需要渲染UI時,它就會在SurfaceFlinger類的成員函數waitForEvent中睡眠等待,直到SurfaceFlinger服務需要執行新的UI渲染操作為止。

      SurfaceFlinger服務什麼時候會需要執行新的UI渲染操作呢?當系統顯示屏屬性發生變化,或者應用程式視窗發生變化時,它就需要重新渲染系統的UI。這時候SurfaceFlinger服務就會從SurfaceFlinger類的成員函數waitEvent中喚醒,并且依次執行SurfaceFlinger類的成員函數handleConsoleEvents、handleTransaction、handlePageFlip、handleRepaint和postFramebuffer來具體執行渲染UI的操作。其中,成員函數handleConsoleEvents用來處理控制台事件;成員函數handleTransaction用來處理系統顯示屏屬性變化以及應用程式視窗屬性變化;成員函數handlePageFlip用來獲得應用程式視窗下一次要渲染的圖形緩沖區,即設定應用程式視窗的活動圖形緩沖區;成員函數handleRepaint用來重繪應用程式視窗;成員函數postFramebuffer用來将系統UI渲染到硬體幀緩沖區中去。

      前面提到, SurfaceFlinger服務在在執行UI渲染操作時,需要調用SurfaceFlinger類的成員函數handleConsoleEvents來處理控制台事件。這怎麼了解呢?原來,SurfaceFlinger服務在啟動的時候,還會建立另外一個線程來監控由核心發出的幀緩沖區硬體事件。為了友善描述,我們将這個線程稱為控制台事件監控線程。每當幀緩沖區要進入睡眠狀态時,核心就會發出一個睡眠事件,這時候SurfaceFlinger服務就會執行一個釋放螢幕的操作;而當幀緩沖區從睡眠狀态喚醒時,核心就會發出一個喚醒事件,這時候SurfaceFlinger服務就會執行一個擷取螢幕的操作。

      這樣,我們就簡要介紹完了SurfaceFlinger類的定義。從這些介紹可以知道:

      1. SurfaceFlinger服務通過一個GraphicPlane對象來管理系統的顯示裝置;

      2. SurfaceFlinger服務有三種類型的線程,它們分别是Binder線程、控制台事件監控線程和UI渲染線程;

      3. SurfaceFlinger服務是在UI渲染線程中執行渲染系統UI的操作的。

      圍繞上述三個内容,再結合SurfaceFlinger服務的啟動過程,接下來我們再通過以下四篇文章來系統地學習SurfaceFlinger服務的實作原理

本文轉自 Luoshengyang 51CTO部落格,原文連結:http://blog.51cto.com/shyluo/1242463,如需轉載請自行聯系原作者

繼續閱讀