原文出處——>[Android應用程序與SurfaceFlinger服務的關系概述和學習計劃](http://blog.csdn.net/luoshengyang/article/details/7846923)
SurfaceFlinger服務負責繪制Android應用程序的UI,它的實現相當復雜,要從正面分析它的實現不是一件容易的事。既然不能從正面分析,我們就想辦法從側面分析。說到底,無論SurfaceFlinger服務有多復雜,它都是為Android應用程序服務的,因此,我們就從Android應用程序與SurfaceFlinger服務的關系入手,來概述和制定SurfaceFlinger服務的學習計劃。
SurfaceFlinger服務運行在Android系統的System進程中,它負責管理Android系統的幀緩沖區(Frame Buffer)。Android系統的幀緩沖區的相關知識,可以參考前面兩篇文章Android系統的開機畫面顯示過程分析和Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析。Android應用程序為了能夠將自己的UI繪制在系統的幀緩沖區上,它們就必須要與SurfaceFlinger服務進行通信,如圖1所示:

圖1 Android應用程序與SurfaceFlinger服務的關系
注意,Android應用程序與SurfaceFlinger服務是運行在不同的進程中的,因此,它們采用Binder進程間通信機制來進行通信。Android系統的Binder進程間通信機制的相關知識,可以參考Android進程間通信(IPC)機制Binder簡要介紹和學習計劃這一系列的文章。
在圖1中,每一個Android應用程序與SurfaceFlinger服務都有一個連接,這個連接都是通過一個類型為Client的Binder對象來描述的。這些Client對象是Android應用程序連接到SurfaceFlinger服務的時候由SurfaceFlinger服務創建的,而當Android應用程序成功連接到SurfaceFlinger服務之后,就可以獲得一個對應的Client對象的Binder代理接口了。有了這些Binder代理接口之后,Android應用程序就可以通知SurfaceFlinger服務來繪制自己的UI了。
Android應用程序在通知SurfaceFlinger服務來繪制自己的UI的時候,需要將UI元數據傳遞給SurfaceFlinger服務,例如,要繪制UI的區域、位置等信息。一個Android應用程序可能會有很多個窗口,而每一個窗口都有自己的UI元數據,因此,Android應用程序需要傳遞給SurfaceFlinger服務的UI元數據是相當可觀的。在這種情況下,通過Binder進程間通信機制來在Android應用程序與SurfaceFlinger服務之間傳遞UI元數據是不合適的,這時候Android系統的匿名共享內存機制(Anonymous Shared Memory)就派上用場了。Android系統的匿名共享內存機制的相關知識,可以參考Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃這一系列的文章。
在每一個Android應用程序與SurfaceFlinger服務之間的連接上加上一塊用來傳遞UI元數據的匿名共享內存,我們就得到了圖2,如下所示:

圖2 用來在Android應用程序與SurfaceFlinger服務之間傳遞UI元數據的匿名共享內存
在Application和Client這兩個高富帥看來,它們之間的原生匿名共享內存塊就一個活脫脫的土肥圓。因此,Application和Client是看不上這塊原生的匿名共享內存的。于是,這塊原生的匿名共享內存當時就怒了,立志要逆襲變成白富美,如圖3所示:

圖3 結構化后的用來傳遞UI元數據的匿名共享內存塊
土肥圓逆襲后,就變成了一個名字為SharedClient的白富美,從此,它就和Application、Client過上幸福的啪啪啪生活了。
SharedClient到底有多白多富多美?參見圖4:

圖4 用來描述Android應用程序的UI元數據的SharedClient
在每一個SharedClient里面,有至多31個SharedBufferStack。字面上來看,SharedBufferStack就是共享緩沖區堆棧。怎么理解呢?首先,Shared表明這個堆棧共享的。那么由誰來共享呢?當然就是Android應用程序和SurfaceFlinger服務了。其次,Buffer表明這個堆棧的內容是緩沖區。什么樣的緩沖區呢?當然就是用來描述UI元數據的緩沖區了。再者,Stack表明用來描述UI元數據的緩沖區是需要按照一定的規則來訪問的。綜合起來,我們就可以認為每一個SharedBufferStack就是用來描述一系列需要按照一定規則來訪問的緩沖區。
好像還是不能理解SharedBufferStack?好吧,回憶一下,一般我們就繪制UI的時候,都會采用一種稱為“雙緩沖”的技術。雙緩沖意味著要使用兩個緩沖區,其中一個稱為Front Buffer,另外一個稱為Back Buffer。UI總是先在Back Buffer中繪制,然后再和Front Buffer交換,渲染到顯示設備中。這下就可以理解SharedBufferStack的含義了吧?SurfaceFlinger服務只不過是將傳統的“雙緩沖”技術升華和抽象為了一個SharedBufferStack。可別小看了這個升華和抽象,有了SharedBufferStack之后,SurfaceFlinger服務就可以使用N個緩沖區技術來繪制UI了。N值的取值范圍為2到16。例如,在Android 2.3中,N的值等于2,而在Android 4.1中,據說就等于3了。
我們還可以再進一步地理解SharedBufferStack。在SurfaceFlinger服務中,每一個SharedBufferStack都對應一個Surface,即一個窗口。這樣,我們就可以知道為什么每一個SharedClient里面包含的是一系列SharedBufferStack而不是單個SharedBufferStack:一個SharedClient對應一個Android應用程序,而一個Android應用程序可能包含有多個窗口,即Surface。從這里也可以看出,一個Android應用程序至多可以包含31個Surface。
SharedBufferStack長什么樣子呢?看圖5:

圖 5 SharedBufferStack的結構示意圖
在圖5中,為了方便描述,我們假設圖中的SharedBufferStack有5個Buffer,其中,Buffer-1和Buffer-2是已經使用了的,而Buffer-3、Buffer-4和Buffer-5是空閑的。指針head和tail分別指向空閑緩沖區列表的頭部和尾部,而指針queue_head指向已經使用了的緩沖區列表的頭部。從這里就可以看出,從指針tail到head之間的Buffer即為空閑緩沖區表,而從指針head到queue_head之間的Buffer即為已經使用了的緩沖區列表。注意,圖中的5個Buffer是循環使用的。
空閑緩沖區比較好理解,接下來我們重點解釋一下那些已經被使用了的緩沖區,即圖5中的Buffer-1和Buffer-2。
前面我們說過,SharedBufferStack中的緩沖區只是用來描述UI元數據的,這意味著它們不包含真正的UI數據。真正的UI數據保存在GraphicBuffer中,后面我們再描述GaphicBuffer。因此,為了完整地描述一個UI,SharedBufferStack中的每一個已經使用了的緩沖區都對應有一個GraphicBuffer,用來描述真正的UI數據。當SurfaceFlinger服務緩制Buffer-1和Buffer-2的時候,就會找到與它們所對應的GraphicBuffer,這樣就可以將對應的UI繪制出來了。
當Android應用程序需要更新一個Surface的時候,它就會找到與它所對應的SharedBufferStack,并且從它的空閑緩沖區列表的尾部取出一個空閑的Buffer。我們假設這個取出來的空閑Buffer的編號為index。接下來Android應用程序就請求SurfaceFlinger服務為這個編號為index的Buffer分配一個圖形緩沖區GraphicBuffer。SurfaceFlinger服務分配好圖形緩沖區GraphicBuffer之后,會將它的編號設置為index,然后再將這個圖形緩沖區GraphicBuffer返回給Android應用程序訪問。Android應用程序得到了SurfaceFlinger服務返回的圖形緩沖區GraphicBuffer之后,就在里面寫入UI數據。寫完之后,就將與它所對應的緩沖區,即編號為index的Buffer,插入到對應的SharedBufferStack的已經使用了的緩沖區列表的頭部去。這一步完成了之后,Android應用程序就通知SurfaceFlinger服務去繪制那些保存在已經使用了的緩沖區所描述的圖形緩沖區GraphicBuffer了。用圖5的例子來說,SurfaceFlinger服務需要繪制的是編號為1和2的Buffer所對應的圖形緩沖區GraphicBuffer。由于SurfaceFlinger服務知道編號為1和2的Buffer所對應的圖形緩沖區GraphicBuffer在哪里,因此,Android應用程序只需要告訴SurfaceFlinger服務要繪制的Buffer的編號就OK了。當一個已經被使用了的Buffer被繪制了之后,它就重新變成一個空閑的Buffer了。
上面描述的過程比較復雜,后面我們再用幾篇文章來詳細描述。
SharedBufferStack是在Android應用程序和SurfaceFlinger服務之間共享的,但是,Android應用程序和SurfaceFlinger服務使用SharedBufferStack的方式是不一樣的,具體來說,就是Android應用程序關心的是它里面的空閑緩沖區列表,而SurfaceFlinger服務關心的是它里面的已經使用了的緩沖區列表。從SurfaceFlinger服務的角度來看,保存在SharedBufferStack中的已經使用了的緩沖區其實就是在排隊等待渲染。
為了方便SharedBufferStack在Android應用程序和SurfaceFlinger服務中的訪問,Android系統分別使用SharedBufferClient和SharedBufferServer來描述SharedBufferStack,其中,SharedBufferClient用來在Android應用程序這一側訪問SharedBufferStack的空閑緩沖區列表,而SharedBufferServer用來在SurfaceFlinger服務這一側訪問SharedBufferStack的排隊緩沖區列表。
在SharedBufferClient看來,SharedBufferStack的樣子如圖6所示:

圖6 SharedBufferClient眼中的SharedBufferStack
只要SharedBufferStack中的available的buffer的數量大于0,SharedBufferClient就會將指針tail往前移一步,并且減少available的值,以便可以獲得一個空閑的Buffer。當Android應用程序往這個空閑的Buffer寫入好數據之后,它就會通過SharedBufferClient來將它添加到SharedBufferStack中的排隊緩沖區列表的尾部去,即指針queue_head的下一個位置上。
在SharedBufferServer看來,SharedBufferStack的樣子如圖7所示:

圖7 SharedBufferServer眼中的SharedBufferStack
當Android應用程序通知SurfaceFlinger服務更新UI的時候,只要對應的SharedBufferStack中的queued的緩沖區的數量大于0,SharedBufferServer就會將指針head的下一個Buffer繪制出來,并且將指針head向前移一步,以及將queued的值減1。
上面我們多次提到了圖形緩沖區GraphicBuffer,它是什么東東呢?我們看圖8:

圖8 圖形緩沖區Graphic的結構示意圖
每一個GraphicBuffer內部都包含有一塊用來保存UI數據的緩沖區,這塊緩沖區使用一個buffer_handle_t對象來描述。看到buffer_handle_t,是不是有點眼熟?在前面Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析一文中,我們說過,由HAL層的Gralloc模塊分配的圖形緩沖區的是使用一個buffer_handle_t對象來描述的,而由buffer_handle_t對象所描述的圖形緩沖區要么是在系統幀緩沖區(Frame Buffer)或者匿名共享內存(Anonymous Shared Memory)中分配的。這樣,我們就可以將SurfaceFlinger服務與HAL層中的Gralloc模塊關聯起來了。
至此,Android應用程序與SurfaceFlinger服務的關系就概述完畢了,但是我們的任務還沒有完成,我們還要進一步去具體地學習它,例如:
1. Android應用程序是如何與SurfaceFlinger服務建立連接的?
2. 用來描述Android應用程序的UI元數據的SharedClient是如何創建的?
3. Android應用程序是如何請求SurfaceFlinger服務創建一個Surface的?
4. Android應用程序是如何請求SurfaceFlinger服務渲染一個Surface的?
回答了這4個問題之后,相信我們就可以對SurfaceFlinger服務有一個深刻的認識,進而可以幫助我們從正面去分析SurfaceFlinger服務的實現。后面我們將以Android系統的開機動畫為例子,用4篇文章來回答這4個問題,敬請關注!
- 前言
- Android組件設計思想
- Android源代碼開發和調試環境搭建
- Android源代碼下載和編譯
- Android源代碼情景分析法
- Android源代碼調試分析法
- 手把手教你為手機編譯ROM
- 在Ubuntu上下載、編譯和安裝Android最新源代碼
- 在Ubuntu上下載、編譯和安裝Android最新內核源代碼(Linux Kernel)
- 如何單獨編譯Android源代碼中的模塊
- 在Ubuntu上為Android系統編寫Linux內核驅動程序
- 在Ubuntu上為Android系統內置C可執行程序測試Linux內核驅動程序
- 在Ubuntu上為Android增加硬件抽象層(HAL)模塊訪問Linux內核驅動程序
- 在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口
- 在Ubuntu上為Android系統的Application Frameworks層增加硬件訪問服務
- 在Ubuntu上為Android系統內置Java應用程序測試Application Frameworks層的硬件服務
- Android源代碼倉庫及其管理工具Repo分析
- Android編譯系統簡要介紹和學習計劃
- Android編譯系統環境初始化過程分析
- Android源代碼編譯命令m/mm/mmm/make分析
- Android系統鏡像文件的打包過程分析
- 從CM刷機過程和原理分析Android系統結構
- Android系統架構概述
- Android系統整體架構
- android專用驅動
- Android硬件抽象層HAL
- Android應用程序組件
- Android應用程序框架
- Android用戶界面架構
- Android虛擬機之Dalvik虛擬機
- Android硬件抽象層
- Android硬件抽象層(HAL)概要介紹和學習計劃
- Android專用驅動
- Android Logger驅動系統
- Android日志系統驅動程序Logger源代碼分析
- Android應用程序框架層和系統運行庫層日志系統源代碼分析
- Android日志系統Logcat源代碼簡要分析
- Android Binder驅動系統
- Android進程間通信(IPC)機制Binder簡要介紹和學習計劃
- 淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路
- 淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路
- Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析
- Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析
- Android系統進程間通信Binder機制在應用程序框架層的Java接口源代碼分析
- Android Ashmem驅動系統
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)驅動程序源代碼分析
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)在進程間共享的原理分析
- Android系統匿名共享內存(Anonymous Shared Memory)C++調用接口分析
- Android應用程序進程管理
- Android應用程序進程啟動過程的源代碼分析
- Android系統進程Zygote啟動過程的源代碼分析
- Android系統默認Home應用程序(Launcher)的啟動過程源代碼分析
- Android應用程序消息機制
- Android應用程序消息處理機制(Looper、Handler)分析
- Android應用程序線程消息循環模型分析
- Android應用程序輸入事件分發和處理機制
- Android應用程序鍵盤(Keyboard)消息處理機制分析
- Android應用程序UI架構
- Android系統的開機畫面顯示過程分析
- Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析
- SurfaceFlinger
- Android系統Surface機制的SurfaceFlinger服務
- SurfaceFlinger服務簡要介紹和學習計劃
- 啟動過程分析
- 對幀緩沖區(Frame Buffer)的管理分析
- 線程模型分析
- 渲染應用程序UI的過程分析
- Android應用程序與SurfaceFlinger服務的關系
- 概述和學習計劃
- 連接過程分析
- 共享UI元數據(SharedClient)的創建過程分析
- 創建Surface的過程分析
- 渲染Surface的過程分析
- Android應用程序窗口(Activity)
- 實現框架簡要介紹和學習計劃
- 運行上下文環境(Context)的創建過程分析
- 窗口對象(Window)的創建過程分析
- 視圖對象(View)的創建過程分析
- 與WindowManagerService服務的連接過程分析
- 繪圖表面(Surface)的創建過程分析
- 測量(Measure)、布局(Layout)和繪制(Draw)過程分析
- WindowManagerService
- WindowManagerService的簡要介紹和學習計劃
- 計算Activity窗口大小的過程分析
- 對窗口的組織方式分析
- 對輸入法窗口(Input Method Window)的管理分析
- 對壁紙窗口(Wallpaper Window)的管理分析
- 計算窗口Z軸位置的過程分析
- 顯示Activity組件的啟動窗口(Starting Window)的過程分析
- 切換Activity窗口(App Transition)的過程分析
- 顯示窗口動畫的原理分析
- Android控件TextView的實現原理分析
- Android視圖SurfaceView的實現原理分析
- Android應用程序UI硬件加速渲染
- 簡要介紹和學習計劃
- 環境初始化過程分析
- 預加載資源地圖集服務(Asset Atlas Service)分析
- Display List構建過程分析
- Display List渲染過程分析
- 動畫執行過程分析
- Android應用程序資源管理框架
- Android資源管理框架(Asset Manager)
- Asset Manager 簡要介紹和學習計劃
- 編譯和打包過程分析
- Asset Manager的創建過程分析
- 查找過程分析
- Dalvik虛擬機和ART虛擬機
- Dalvik虛擬機
- Dalvik虛擬機簡要介紹和學習計劃
- Dalvik虛擬機的啟動過程分析
- Dalvik虛擬機的運行過程分析
- Dalvik虛擬機JNI方法的注冊過程分析
- Dalvik虛擬機進程和線程的創建過程分析
- Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃
- Dalvik虛擬機Java堆創建過程分析
- Dalvik虛擬機為新創建對象分配內存的過程分析
- Dalvik虛擬機垃圾收集(GC)過程分析
- ART虛擬機
- Android ART運行時無縫替換Dalvik虛擬機的過程分析
- Android運行時ART簡要介紹和學習計劃
- Android運行時ART加載OAT文件的過程分析
- Android運行時ART加載類和方法的過程分析
- Android運行時ART執行類方法的過程分析
- ART運行時垃圾收集機制簡要介紹和學習計劃
- ART運行時Java堆創建過程分析
- ART運行時為新創建對象分配內存的過程分析
- ART運行時垃圾收集(GC)過程分析
- ART運行時Compacting GC簡要介紹和學習計劃
- ART運行時Compacting GC堆創建過程分析
- ART運行時Compacting GC為新創建對象分配內存的過程分析
- ART運行時Semi-Space(SS)和Generational Semi-Space(GSS)GC執行過程分析
- ART運行時Mark-Compact( MC)GC執行過程分析
- ART運行時Foreground GC和Background GC切換過程分析
- Android安全機制
- SEAndroid安全機制簡要介紹和學習計劃
- SEAndroid安全機制框架分析
- SEAndroid安全機制中的文件安全上下文關聯分析
- SEAndroid安全機制中的進程安全上下文關聯分析
- SEAndroid安全機制對Android屬性訪問的保護分析
- SEAndroid安全機制對Binder IPC的保護分析
- 從NDK在非Root手機上的調試原理探討Android的安全機制
- APK防反編譯
- Android視頻硬解穩定性問題探討和處理
- Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析
- Android應用程序安裝過程源代碼分析
- Android應用程序啟動過程源代碼分析
- 四大組件源代碼分析
- Activity
- Android應用程序的Activity啟動過程簡要介紹和學習計劃
- Android應用程序內部啟動Activity過程(startActivity)的源代碼分析
- 解開Android應用程序組件Activity的"singleTask"之謎
- Android應用程序在新的進程中啟動新的Activity的方法和過程分析
- Service
- Android應用程序綁定服務(bindService)的過程源代碼分析
- ContentProvider
- Android應用程序組件Content Provider簡要介紹和學習計劃
- Android應用程序組件Content Provider應用實例
- Android應用程序組件Content Provider的啟動過程源代碼分析
- Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
- Android應用程序組件Content Provider的共享數據更新通知機制分析
- BroadcastReceiver
- Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃
- Android應用程序注冊廣播接收器(registerReceiver)的過程分析
- Android應用程序發送廣播(sendBroadcast)的過程分析