SurfaceFlinger在系統(tǒng)啟動(dòng)階段作為系統(tǒng)服務(wù)被加載。應(yīng)用程序中的每個(gè)窗口,對應(yīng)本地代碼中的Surface,而Surface又對應(yīng)于SurfaceFlinger中的各個(gè)Layer,SurfaceFlinger的主要作用是為這些Layer申請內(nèi)存,根據(jù)應(yīng)用程序的請求管理這些Layer顯示、隱藏、重畫等操作,最終由SurfaceFlinger把所有的Layer組合到一起,顯示到顯示器上。當(dāng)一個(gè)應(yīng)用程序需要在一個(gè)Surface上進(jìn)行畫圖操作時(shí),首先要拿到這個(gè)Surface在內(nèi)存中的起始地址,而這塊內(nèi)存是在SurfaceFlinger中分配的,因?yàn)镾urfaceFlinger和應(yīng)用程序并不是運(yùn)行在同一個(gè)進(jìn)程中,如何在應(yīng)用客戶端(Surface)和服務(wù)端(SurfaceFlinger -Layer)之間傳遞和同步顯示緩沖區(qū)?這正是本文要討論的內(nèi)容。
我們先看看Android如何創(chuàng)建一個(gè)Surface,下面的序列圖展示了整個(gè)創(chuàng)建過程。
圖一 Surface的創(chuàng)建過程
創(chuàng)建Surface的過程基本上分為兩步:
1. 建立SurfaceSession
第一步通常只執(zhí)行一次,目的是創(chuàng)建一個(gè)SurfaceComposerClient的實(shí)例,JAVA層通過JNI調(diào)用本地代碼,本地代碼創(chuàng)建一個(gè)SurfaceComposerClient的實(shí)例,SurfaceComposerClient通過ISurfaceComposer接口調(diào)用SurfaceFlinger的createConnection,SurfaceFlinger返回一個(gè)ISurfaceFlingerClient接口給SurfaceComposerClient,在createConnection的過程中,SurfaceFlinger創(chuàng)建了用于管理緩沖區(qū)切換的SharedClient,關(guān)于SharedClient我們下面再介紹,最后,本地層把SurfaceComposerClient的實(shí)例返回給JAVA層,完成SurfaceSession的建立。
2. 利用SurfaceSession創(chuàng)建Surface
JAVA層通過JNI調(diào)用本地代碼Surface_Init(),本地代碼首先取得第一步創(chuàng)建的SurfaceComposerClient實(shí)例,通過SurfaceComposerClient,調(diào)用ISurfaceFlingerClient接口的createSurface方法,進(jìn)入SurfaceFlinger,SurfaceFlinger根據(jù)參數(shù),創(chuàng)建不同類型的Layer,然后調(diào)用Layer的setBuffers()方法,為該Layer創(chuàng)建了兩個(gè)緩沖區(qū),然后返回該Layer的ISurface接口,SurfaceComposerClient使用這個(gè)ISurface接口創(chuàng)建一個(gè)SurfaceControl實(shí)例,并把這個(gè)SurfaceControl返回給JAVA層。
由此得到以下結(jié)果:
雖然在SurfaceFlinger在創(chuàng)建Layer時(shí)已經(jīng)為每個(gè)Layer申請了兩個(gè)緩沖區(qū),但是此時(shí)在JAVA層并看不到這兩個(gè)緩沖區(qū),JAVA層要想在Surface上進(jìn)行畫圖操作,必須要先把其中的一個(gè)緩沖區(qū)綁定到Canvas中,然后所有對該Canvas的畫圖操作最后都會(huì)畫到該緩沖區(qū)內(nèi)。下圖展現(xiàn)了綁定緩沖區(qū)的過程:
圖二 綁定緩沖區(qū)的過程
開始在Surface畫圖前,Surface.java會(huì)先調(diào)用lockCanvas()來得到要進(jìn)行畫圖操作的Canvas,lockCanvas會(huì)進(jìn)一步調(diào)用本地層的Surface_lockCanvas,本地代碼利用JAVA層傳入的SurfaceControl對象,通過getSurface()取得本地層的Surface對象,接著調(diào)用該Surface對象的lock()方法,lock()返回了改Surface的信息,其中包括了可用緩沖區(qū)的首地址vaddr,該vaddr在Android的2D圖形庫Skia中,創(chuàng)建了一個(gè)bitmap,然后通過Skia庫中Canvas的API:Canvas.setBitmapDevice(bitmap),把該bitmap綁定到Canvas中,最后把這個(gè)Canvas返回給JAVA層,這樣JAVA層就可以在該Canvas上進(jìn)行畫圖操作,而這些畫圖操作最終都會(huì)畫在以vaddr為首地址的緩沖區(qū)中。
再看看在Surface的lock()方法中做了什么:
畫圖完成后,要想把Surface的內(nèi)容顯示到屏幕上,需要把Canvas中綁定的緩沖區(qū)釋放,并且把該緩沖區(qū)從變成可投遞(因?yàn)槟J(rèn)只有兩個(gè)buffer,所以實(shí)際上就是變成了frontBuffer),SurfaceFlinger的工作線程會(huì)在適當(dāng)?shù)乃⑿聲r(shí)刻,把系統(tǒng)中所有的frontBuffer混合在一起,然后通過OpenGL刷新到屏幕上。下圖展現(xiàn)了解除綁定緩沖區(qū)的過程:
圖三 解除綁定緩沖區(qū)的過程
從前面的討論可以看到,Canvas綁定緩沖區(qū)時(shí),要通過SharedBufferClient的dequeue方法取得空閑的緩沖區(qū),而解除綁定并提交緩沖區(qū)投遞時(shí),最后也要調(diào)用SharedBufferClient的queue方法通知SurfaceFlinger的工作線程。實(shí)際上,在SurfaceFlinger里,每個(gè)Layer也會(huì)關(guān)聯(lián)一個(gè)SharedBufferServer,SurfaceFlinger的工作線程通過SharedBufferServer管理著Layer的緩沖區(qū),在SurfaceComposerClient建立連接的階段,SurfaceFlinger就已經(jīng)為該連接創(chuàng)建了一個(gè)SharedClient 對象,SharedClient對象中包含了一個(gè)SharedBufferStack數(shù)組,數(shù)組的大小是31,每當(dāng)創(chuàng)建一個(gè)Surface,就會(huì)占用數(shù)組中的一個(gè)SharedBufferStack,然后SurfaceComposerClient端的Surface會(huì)創(chuàng)建一個(gè)SharedBufferClient和該SharedBufferStack關(guān)聯(lián),而SurfaceFlinger端的Layer也會(huì)創(chuàng)建SharedBufferServer和SharedBufferStack關(guān)聯(lián),實(shí)際上每對SharedBufferClient/SharedBufferServer是控制著同一個(gè)SharedBufferStack對象,通過SharedBufferStack,保證了負(fù)責(zé)對Surface的畫圖操作的應(yīng)用端和負(fù)責(zé)刷新屏幕的服務(wù)端(SurfaceFlinger)可以使用不同的緩沖區(qū),并且讓他們之間知道對方何時(shí)鎖定/釋放緩沖區(qū)。
SharedClient和SharedBufferStack的代碼和頭文件分別位于:
/frameworks/base/libs/surfaceflinger_client/SharedBufferStack.cpp
/frameworks/base/include/private/surfaceflinger/SharedBufferStack.h
圖四 客戶端和服務(wù)端緩沖區(qū)管理
繼續(xù)研究SharedClient、SharedBufferStack、SharedBufferClient、SharedBufferServer的誕生過程。
SharedClient對象中有一個(gè)SharedBufferStack數(shù)組:
SharedBufferStack surfaces[ NUM_LAYERS_MAX ];
NUM_LAYERS_MAX被定義為31,這樣保證了SharedClient對象的大小正好滿足4KB的要求。創(chuàng)建一個(gè)新的Surface時(shí),進(jìn)入SurfaceFlinger的createSurface函數(shù)后,先取在createConnection階段創(chuàng)建的Client對象,通過Client在0--NUM_LAYERS_MAX 之間取得一個(gè)尚未被使用的編號(hào),這個(gè)編號(hào)實(shí)際上就是SharedBufferStack數(shù)組的索引:
然后以Client對象和索引值以及其他參數(shù),創(chuàng)建不同類型的Layer對象,一普通的Layer對象為例:
在createNormalSurfaceLocked中創(chuàng)建Layer對象:
構(gòu)造Layer時(shí)會(huì)先構(gòu)造的父類LayerBaseClient,LayerBaseClient中創(chuàng)建了SharedBufferServer對象,SharedBufferStack 數(shù)組的索引值和SharedClient被傳入SharedBufferServer對象中。
自此,Layer通過lcblk成員變量(SharedBufferServer)和SharedClient共享內(nèi)存區(qū)建立了關(guān)聯(lián),并且每個(gè)Layer對應(yīng)于SharedBufferStack 數(shù)組中的一項(xiàng)。
回到SurfaceFlinger的客戶端Surface.cpp中,Surface的構(gòu)造函數(shù)如下:
SharedBufferClient構(gòu)造參數(shù)mClient->mControl就是共享內(nèi)存塊中的SharedClient對象,mToken就是SharedBufferStack 數(shù)組索引值。
聯(lián)系客服