SurfaceFlinger在系統(tǒng)啟動階段作為系統(tǒng)服務(wù)被加載。應(yīng)用程序中的每個窗口,對應(yīng)本地代碼中的Surface,而Surface又對應(yīng)于 SurfaceFlinger中的各個Layer,SurfaceFlinger的主要作用是為這些Layer申請內(nèi)存,根據(jù)應(yīng)用程序的請求管理這些 Layer顯示、隱藏、重畫等操作,最終由SurfaceFlinger把所有的Layer組合到一起,顯示到顯示器上。當一個應(yīng)用程序需要在一個 Surface上進行畫圖操作時,首先要拿到這個Surface在內(nèi)存中的起始地址,而這塊內(nèi)存是在SurfaceFlinger中分配的,因為 SurfaceFlinger和應(yīng)用程序并不是運行在同一個進程中,如何在應(yīng)用客戶端(Surface)和服務(wù)端(SurfaceFlinger - Layer)之間傳遞和同步顯示緩沖區(qū)?這正是本文要討論的內(nèi)容。
Surface的創(chuàng)建過程
我們先看看Android如何創(chuàng)建一個Surface,下面的序列圖展示了整個創(chuàng)建過程。

圖一 Surface的創(chuàng)建過程
創(chuàng)建Surface的過程基本上分為兩步:
1. 建立SurfaceSession
第一步通常只執(zhí)行一次,目的是創(chuàng)建一個SurfaceComposerClient的實例,JAVA層通過JNI調(diào)用本地代碼,本地代碼創(chuàng)建一個 SurfaceComposerClient的實例,SurfaceComposerClient通過ISurfaceComposer接口調(diào)用 SurfaceFlinger的createConnection,SurfaceFlinger返回一個ISurfaceFlingerClient接 口給SurfaceComposerClient,在createConnection的過程中,SurfaceFlinger創(chuàng)建了用于管理緩沖區(qū)切換 的SharedClient,關(guān)于SharedClient我們下面再介紹,最后,本地層把SurfaceComposerClient的實例返回給 JAVA層,完成SurfaceSession的建立。
2. 利用SurfaceSession創(chuàng)建Surface
JAVA層通過JNI調(diào)用本地代碼Surface_Init(),本地代碼首先取得第一步創(chuàng)建的SurfaceComposerClient實例, 通過SurfaceComposerClient,調(diào)用ISurfaceFlingerClient接口的createSurface方法,進入 SurfaceFlinger,SurfaceFlinger根據(jù)參數(shù),創(chuàng)建不同類型的Layer,然后調(diào)用Layer的setBuffers()方法, 為該Layer創(chuàng)建了兩個緩沖區(qū),然后返回該Layer的ISurface接口,SurfaceComposerClient使用這個ISurface接 口創(chuàng)建一個SurfaceControl實例,并把這個SurfaceControl返回給JAVA層。
由此得到以下結(jié)果:
- JAVA層的Surface實際上對應(yīng)于本地層的SurfaceControl對象,以后本地代碼可以使用JAVA傳入的SurfaceControl對象,通過SurfaceControl的getSurface方法,獲得本地Surface對象;
- Android為每個Surface分配了兩個圖形緩沖區(qū),以便實現(xiàn)Page-Flip的動作;
- 建立SurfaceSession時,SurfaceFlinger創(chuàng)建了用于管理兩個圖形緩沖區(qū)切換的SharedClient對 象,SurfaceComposerClient可以通過ISurfaceFlingerClient接口的getControlBlock()方法獲得 這個SharedClient對象,查看SurfaceComposerClient的成員函數(shù)_init:
- void SurfaceComposerClient::_init(
- const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn)
- {
- ......
- mClient = conn;
- if (mClient == 0) {
- mStatus = NO_INIT;
- return;
- }
-
- mControlMemory = mClient->getControlBlock();
- mSignalServer = sm;
- mControl = static_cast<SharedClient *>(mControlMemory->getBase());
- }
獲得Surface對應(yīng)的顯示緩沖區(qū)
雖然在SurfaceFlinger在創(chuàng)建Layer時已經(jīng)為每個Layer申請了兩個緩沖區(qū),但是此時在JAVA層并看不到這兩個緩沖 區(qū),JAVA層要想在Surface上進行畫圖操作,必須要先把其中的一個緩沖區(qū)綁定到Canvas中,然后所有對該Canvas的畫圖操作最后都會畫到 該緩沖區(qū)內(nèi)。下圖展現(xiàn)了綁定緩沖區(qū)的過程:

圖二 綁定緩沖區(qū)的過程
開始在Surface畫圖前,Surface.java會先調(diào)用lockCanvas()來得到要進行畫圖操作的Canvas,lockCanvas會進 一步調(diào)用本地層的Surface_lockCanvas,本地代碼利用JAVA層傳入的SurfaceControl對象,通過getSurface() 取得本地層的Surface對象,接著調(diào)用該Surface對象的lock()方法,lock()返回了改Surface的信息,其中包括了可用緩沖區(qū)的 首地址vaddr,該vaddr在Android的2D圖形庫Skia中,創(chuàng)建了一個bitmap,然后通過Skia庫中Canvas的 API:Canvas.setBitmapDevice(bitmap),把該bitmap綁定到Canvas中,最后把這個Canvas返回給JAVA 層,這樣JAVA層就可以在該Canvas上進行畫圖操作,而這些畫圖操作最終都會畫在以vaddr為首地址的緩沖區(qū)中。
再看看在Surface的lock()方法中做了什么:
- dequeueBuffer(&backBuffer)獲取backBuffer
- SharedBufferClient->dequeue()獲得當前空閑緩沖區(qū)的編號
- 通過緩沖區(qū)編號獲得真正的GraphicBuffer:backBuffer
- 如果還沒有對Layer中的buffer進行映射(Mapper),getBufferLocked通過ISurface接口重新重新映射
- 獲取frontBuffer
- 根據(jù)兩個Buffer的更新區(qū)域,把frontBuffer的內(nèi)容拷貝到backBuffer中,這樣保證了兩個Buffer中顯示內(nèi)容的同步
- backBuffer->lock() 獲得backBuffer緩沖區(qū)的首地址vaddr
- 通過info參數(shù)返回vaddr
釋放Surface對應(yīng)的顯示緩沖區(qū)
畫圖完成后,要想把Surface的內(nèi)容顯示到屏幕上,需要把Canvas中綁定的緩沖區(qū)釋放,并且把該緩沖區(qū)從變成可投遞(因為默認只有兩個 buffer,所以實際上就是變成了frontBuffer),SurfaceFlinger的工作線程會在適當?shù)乃⑿聲r刻,把系統(tǒng)中所有的 frontBuffer混合在一起,然后通過OpenGL刷新到屏幕上。下圖展現(xiàn)了解除綁定緩沖區(qū)的過程:

圖三 解除綁定緩沖區(qū)的過程
- JAVA層調(diào)用unlockCanvasAndPost
- 進入本地代碼:Surface_unlockCanvasAndPost
- 本地代碼利用JAVA層傳入的SurfaceControl對象,通過getSurface()取得本地層的Surface對象
- 綁定一個空的bitmap到Canvas中
- 調(diào)用Surface的unlockAndPost方法
- 調(diào)用GraphicBuffer的unlock(),解鎖緩沖區(qū)
- 在queueBuffer()調(diào)用了SharedBufferClient的queue(),把該緩沖區(qū)更新為可投遞狀態(tài)
SharedClient 和 SharedBufferStack
從前面的討論可以看到,Canvas綁定緩沖區(qū)時,要通過SharedBufferClient的dequeue方法取得空閑的緩沖區(qū),而解除綁定 并提交緩沖區(qū)投遞時,最后也要調(diào)用SharedBufferClient的queue方法通知SurfaceFlinger的工作線程。實際上,在 SurfaceFlinger里,每個Layer也會關(guān)聯(lián)一個SharedBufferServer,SurfaceFlinger的工作線程通過 SharedBufferServer管理著Layer的緩沖區(qū),在SurfaceComposerClient建立連接的階 段,SurfaceFlinger就已經(jīng)為該連接創(chuàng)建了一個SharedClient 對象,SharedClient 對象中包含了一個SharedBufferStack數(shù)組,數(shù)組的大小是31,每當創(chuàng)建一個Surface,就會占用數(shù)組中的一個 SharedBufferStack,然后SurfaceComposerClient端的Surface會創(chuàng)建一個 SharedBufferClient和該SharedBufferStack關(guān)聯(lián),而SurfaceFlinger端的Layer也會創(chuàng)建 SharedBufferServer和SharedBufferStack關(guān)聯(lián),實際上每對 SharedBufferClient/SharedBufferServer是控制著同一個SharedBufferStack對象,通過 SharedBufferStack,保證了負責對Surface的畫圖操作的應(yīng)用端和負責刷新屏幕的服務(wù)端(SurfaceFlinger)可以使用不 同的緩沖區(qū),并且讓他們之間知道對方何時鎖定/釋放緩沖區(qū)。
SharedClient和SharedBufferStack的代碼和頭文件分別位于:
/frameworks/base/libs/surfaceflinger_client/SharedBufferStack.cpp
/frameworks/base/include/private/surfaceflinger/SharedBufferStack.h

圖四 客戶端和服務(wù)端緩沖區(qū)管理
繼續(xù)研究SharedClient、SharedBufferStack、SharedBufferClient、SharedBufferServer的誕生過程。
1. SharedClient
- 在createConnection階段,SurfaceFlinger創(chuàng)建Client對象:
- sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
- {
- Mutex::Autolock _l(mStateLock);
- uint32_t token = mTokens.acquire();
-
- sp<Client> client = new Client(token, this);
- if (client->ctrlblk == 0) {
- mTokens.release(token);
- return 0;
- }
- status_t err = mClientsMap.add(token, client);
- if (err < 0) {
- mTokens.release(token);
- return 0;
- }
- sp<BClient> bclient =
- new BClient(this, token, client->getControlBlockMemory());
- return bclient;
- }
- 再進入Client的構(gòu)造函數(shù)中,它分配了4K大小的共享內(nèi)存,并在這塊內(nèi)存上構(gòu)建了SharedClient對象:
- Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
- : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
- {
- const int pgsize = getpagesize();
- const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
-
- mCblkHeap = new MemoryHeapBase(cblksize, 0,
- "SurfaceFlinger Client control-block");
-
- ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
- if (ctrlblk) { // construct the shared structure in-place.
- new(ctrlblk) SharedClient;
- }
- }
- 回到createConnection中,通過Client的getControlBlockMemory()方法獲得共享內(nèi)存塊的 IMemoryHeap接口,接著創(chuàng)建ISurfaceFlingerClient的子類BClient,BClient的成員變量mCblk保存了 IMemoryHeap接口指針;
- 把BClient返回給SurfaceComposerClient,SurfaceComposerClient通過 ISurfaceFlingerClient接口的getControlBlock()方法獲得IMemoryHeap接口指針,同時保存在 SurfaceComposerClient的成員變量mControlMemory中;
- 繼續(xù)通過IMemoryHeap接口的getBase ()方法獲取共享內(nèi)存的首地址,轉(zhuǎn)換為SharedClient指針后保存在SurfaceComposerClient的成員變量mControl中;
- 至此,SurfaceComposerClient的成員變量mControl和SurfaceFlinger::Client.ctrlblk指向了同一個內(nèi)存塊,該內(nèi)存塊上就是SharedClient對象。
2. SharedBufferStack、SharedBufferServer、SharedBufferClient
SharedClient對象中有一個SharedBufferStack數(shù)組:
SharedBufferStack surfaces[ NUM_LAYERS_MAX ];
NUM_LAYERS_MAX 被定義為31,這樣保證了SharedClient對象的大小正好滿足4KB的要求。創(chuàng)建一個新的Surface時,進入SurfaceFlinger的 createSurface函數(shù)后,先取在createConnection階段創(chuàng)建的Client對象,通過Client在 0--NUM_LAYERS_MAX 之間取得一個尚未被使用的編號,這個編號實際上就是SharedBufferStack數(shù)組的索引:
- int32_t id = client->generateId(pid);
然后以Client對象和索引值以及其他參數(shù),創(chuàng)建不同類型的Layer對象,一普通的Layer對象為例:
- layer = createNormalSurfaceLocked(client, d, id,
- w, h, flags, format);
在createNormalSurfaceLocked中創(chuàng)建Layer對象:
- sp<Layer> layer = new Layer(this, display, client, id);
構(gòu)造Layer時會先構(gòu)造的父類LayerBaseClient,LayerBaseClient中創(chuàng)建了SharedBufferServer對 象,SharedBufferStack 數(shù)組的索引值和SharedClient被傳入SharedBufferServer對象中。
- LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
- const sp<Client>& client, int32_t i)
- : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i),
- mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
- {
- lcblk = new SharedBufferServer(
- client->ctrlblk, i, NUM_BUFFERS,
- mIdentity);
- }
自此,Layer通過lcblk成員變量(SharedBufferServer)和SharedClient共享內(nèi)存區(qū)建立了關(guān)聯(lián),并且每個Layer對應(yīng)于SharedBufferStack 數(shù)組中的一項。
回到SurfaceFlinger的客戶端Surface.cpp中,Surface的構(gòu)造函數(shù)如下:
- Surface::Surface(const sp<SurfaceControl>& surface)
- : mClient(surface->mClient), mSurface(surface->mSurface),
- mToken(surface->mToken), mIdentity(surface->mIdentity),
- mFormat(surface->mFormat), mFlags(surface->mFlags),
- mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),
- mWidth(surface->mWidth), mHeight(surface->mHeight)
- {
- mSharedBufferClient = new SharedBufferClient(
- mClient->mControl, mToken, 2, mIdentity);
-
- init();
- }
SharedBufferClient構(gòu)造參數(shù)mClient->mControl就是共享內(nèi)存塊中的SharedClient對象,mToken就是SharedBufferStack 數(shù)組索引值。
到這里我們終于知道,Surface中的mSharedBufferClient成 員和Layer中的lcblk成員(SharedBufferServer),通過SharedClient中的同一個 SharedBufferStack,共同管理著Surface(Layer)中的兩個緩沖區(qū)。
一并參考:
http://wenku.baidu.com/view/0243844bc850ad02de8041e6.html