1、Overviewjava
上圖的原型取自高通的文檔,因爲原圖沒法描述現有的架構,我在原圖的基礎了作了些修改,主要是增長了overlay部分,另外其餘部分根據現有的軟件也作了些許改動。下面先對上圖作個大概的介紹,後面會針對重點部分作詳細的分析。android
最上面一層爲應用程序,根據數據類型以及應用的不一樣能夠分爲幾種。c++
第一種是最普通的應用,如UI界面的顯示,這部分一般數據類型爲RGB格式,數據無須再通過特殊的處理。該應用能夠說遍及各個應用程序,幾乎是實時存在的。api
第二種是針對大塊YUV數據的應用,如camera的preview、視頻的播放等。該應用只針對特定的應用程序,開啓時經過overlay直接把大塊的YUV數據送到kernel顯示。架構
第三種其實和第一種相似,只不過因爲應用的需求在顯示以前須要對數據進行2D、3D的處理(使用OpenGL、OpenVG、SVG、SKIA),處理以後的流程和普通的顯示就沒什麼差異了。通常在Game、地圖、Flash等應用中會用到。app
應用之下是framework,其中最核心的就是surfaceflinger了,它爲全部的應用程序的顯示提供服務。因爲overlay的接口掛在surfaceflinger裏面(雖然2者在功能上不相干),全部使用overlay的AP須要經過surfaceflinger才能夠訪問overlay;另外,因爲surfaceflinger須要使用OpenGL來compose surface,這也就是爲何surfacelfinger會調用EGL wrapper了,EGL wrapper是對Graphics HAL的封裝,除了surfaceflinger會調用它來compose surface外,上層的2D、3D應用也會調用它來進行圖形處理。composer
再下一層就是HAL了。框架
首先一個是overlay模塊,對上提供control channel和data channel;對下則經過系統調用到kernel中的MDP driver。ide
再一個是Gralloc模塊,注意它是和overlay並列的,它包含2個部分,一部分是爲上層提供pmem的接口,另外一部分則是對framebuffer進行刷新,這裏的framebuffer其實就是UI的數據。因而可知上層有2個通道把顯示數據送到kernel中,framebuffer是傳統的方式,overlay是android(éclair之後)後增長的。函數
紅色及右邊部分是OpenGL的HAL,其中紅色部分表明HW solution,高通提供的,這部分是沒有源碼的;右邊的software graphics library是SW solution,android自身的。HW和SW solution能夠同時存在也能夠只有一個,後面會講解。
再往下就是kernel中的driver了,最主要的就是fb設備驅動以及MDP4 overlay的驅動,從硬件上看2者是並列的,framebuffer最終也是經過overlay方式送入MDP的。PMEM和KGSL分別對應kernel中pmem的driver(/dev/pmem)和Adreno220的driver。
2、Surfaceflinger詳解
1.overview
Surfaceflinger能夠說是Android顯示系統中的核心,在android當中它是一個service,提供系統範圍內的surface composer 功能,它可以將各類應用程序的2D 、3D surface 進行組合,合併最終獲得的一個main surface數據會送入顯存。簡單的說,surfaceflinger就像是畫布,它不關心畫上去的內容,只是一味的執行合成功能,固然要根據畫的位置、大小以及效果等參數。這很像Photoshop中的各個Layer,你能夠在不一樣的layer畫任意的內容,每一個layer能夠設置位置、大小、效果參數等,最終經過merge合成一個layer。
從應用的角度看,每一個應用程序可能對應一個或多個圖形界面,每一個界面能夠看做是一個surface。首先每一個surface有它的位置、大小、內容等元素,這些元素是能夠隨便變化的;另外不一樣的surface的位置會有重疊,會涉及到透明度等效果處理問題,這些都是經過surfaceflinger來完成的。固然了,surfaceflinger擔任是一個管理的職責,對於效果處理及合成它是經過OpenGL來作的,但前提是surfaceflinger須要把相關參數計算好,如重疊的位置等。
2.Surfaceflinger在系統中的位置
Android中的圖形系統採用Client/Server架構。服務端負責Surface的合成等處理工做,客戶端提供接口給上層操做本身的Surface,並向服務端發送消息完成實際處理工做。服務端 (即SurfaceFlinger)主要由c++代碼編寫而成。客戶端端代碼分爲兩部分,一部分是由Java提供的供應用使用的api,另外一部分則是由c++寫成的底層實現。以下圖所示:
除去最上層的應用不算,surface最上層的接口就是java surface了,文件路徑以下:
frameworks/base/core/java/android/view/Surface.java,該文件中的接口會被應用間接調用。
咱們從JNI開始看,surface的JNI文件路徑以下:
frameworks/base/core/jni/android_view_Surface.cpp,裏面的接口大概分爲2類,一類是負責管理ibinder通訊的;另外一類纔是和顯示控制相關的,第二類接口會直接調用C實現函數。
C實現的文件路徑以下:
frameworks/base/libs/ui/Surface.cpp
咱們來看看JNI中一些重要的接口:
SurfaceSession_init:本接口只會被調用一次,負責建立surfacecomposerclient,主要爲進程間通訊作準備。對應的銷燬函數有SurfaceSession_destroy和SurfaceSession_kill。
Surface_init:負責建立surface,最終會調用到surfaceflinger中的createSurface,對應的銷燬函數有Surface_destroy和Surface_release。
Surface_lockCanvas:當對一個surface進行繪圖以前要調用的,將該surface鎖定,而且獲得surface的back buffer,應用能夠繪圖。
Surface_unlockCanvasAndPost:當上層繪圖完畢後,經過該函數通知底層back buffer已繪製完畢,能夠更新到顯存中。
Surface_setLayer/
Surface_setPosition/
Surface_setSize/
Surface_hide/
Surface_show/
Surface_setOrientation/
Surface_freeze/
Surface_unfreeze
Surface_setFlags/
Surface_setAlpha/
Surface_setMatrix:設置surface的一些屬性,如大小、位置、方位、截取範圍,Z-order等。其最終改變的都是surface的結構體屬性,以下:
uint32_t what;//哪一項屬性改變
int32_t x;//顯示位置
int32_t y; //顯示位置
uint32_t z; //layer順序
uint32_t w;//寬度
uint32_t h;//高度
float alpha;//透明度
uint32_t tint;//色彩,未使用
uint8_t flags;// 標誌
uint8_t mask;//屏蔽命令
uint8_t reserved;
matrix22_t matrix;//截取範圍
Region transparentRegion;//透明度設置
3.JNI與Surfaceflinger的鏈接通信
因爲JNI及C函數實現與surfaceflinger不在同一個進程(一個在應用端-客戶端,另外一個在服務端),android中經過IPC(Binder)方式實現進程間通訊,下圖來源於網上,不過我修改了裏面的一些錯誤,它演示了JNI和surfaceflinger創建鏈接以及建立surface的流程。
JNI和C函數實現咱們看做是一個部分
這裏看到一個比較重要的部分——SurfaceComposerClient,它是surfacelinger的客戶端,經過它上層才能夠和surfaceflinger使用Binder聯繫到一塊兒,IsurfaceComposer和IsurfaceFlingerClient都是用來實現Binder通訊的。具體流程講解 以下:
應用程序經過JNI接口SurfaceSession_init建立SurfaceComposerClient。經過SurfaceComposerClient函數中調用getComposerService得到IsurfaceComposer的IBinder對象,而後經過這個對象的createConnection又得到IsurfaceFlingerClient的IBinder,經過這個IBinder,JNI就能夠調用Surfaceflinger中的接口了,如createSurface。因爲採用Binder方式,代碼部分稍微複雜一些,須要多看幾遍才能把流程理清楚。
4.Surfaceflinger與libui、OpenGL、顯示設備的鏈接
這裏不得不提到android對媒體框架中一個很重要的部分,那就是libui,它是一個框架庫提供對底層操做的接口,好比會調用Gralloc、Overlay等HAL層接口。其餘的庫類繼承的方式來調用libui,surfaceflinger就是這樣和顯示設備鏈接的(包括寫顯存和對pmem的使用)
Surfaceflinger使用OpenGL來合成surface,因此surfaceflinger會直接調用到OpenGL的接口。
它們的架構以下:
這部分的流程比較複雜,主要是各個類的繼承繞的比較多,我也是看了不少遍代碼以及參考了些資料才理出來,下面來詳細解釋下這個圖:
Surfaceflinger在設計時考慮到支持多個屏幕,但目前的版本只支持一個,在surfaceflinger當中一個顯示設備對應一個圖中的DisplayHardware,surfaceflinger在初始化時會新建Displayhardware(請參考surfaceflinger.cpp中的readyToRun函數),它完成的主要任務一個是創建FramebufferNativeWindow,肯定數據輸出設備接口(請參考FramebufferNativeWindow.cpp),再一個就是初始化OpenGL,並建立main surface,後續surfaceflinger中全部的layer最終都將被畫到這個main surface上(請參考displayhardware.cpp的init函數)。這樣main surface、OpenGL和libui中的FramebufferNativeWindow接口就綁定在一塊兒。
因爲libEGL負責全部layer的最終合成,因此最後數據送往HAL必定要libEGL來觸發,對應的函數流程是:
postFrameBuffer(surfaceflinger)->Flip(displayhardware)-> eglSwapBuffers(OpenGL)-> queueBuffer(libui)->fbpost(gralloc)
另外圖中的GraphicBuffer是libui中提供的對pmem的操做接口,它會直接調用gralloc模塊。關於OpenGL和Gralloc後面會有單獨的章節來介紹。