天天看點

Android應用程式請求SurfaceFlinger服務建立Surface的過程分析

 前面我們已經學習過Android應用程式與SurfaceFlinger服務的連接配接過程了。連接配接上SurfaceFlinger服務之後,Android應用程式就可以請求SurfaceFlinger服務建立Surface。而當有了Surface後,Android應用程式就可以用來渲染自己的UI了。在本文中,我們将詳細分析Android應用程式請求SurfaceFlinger服務建立Surface的過程。

        在講述Android應用程式請求SurfaceFlinger服務建立Surface之前,我們首先了解一個Surface是由什麼組成的。我們可以将Surface了解為一個繪圖表面,Android應用程式負責往這個繪圖表面填内容,而SurfaceFlinger服務負責将這個繪圖表面的内容取出來,并且渲染在顯示屏上。

        在SurfaceFlinger服務這一側,繪圖表面使用Layer類來描述,Layer類的實作如圖1所示。

圖1 Layer類的實作

       Layer類繼承了LayerBaseClient類;LayerBaseClient類繼承了LayerBase類;LayerBase類繼續了RefBase類。從這些繼承關系就可以看出,我們可以通過​​Android系統的智能指針​​來引用Layer對象,進而可以自動地維護它們的生命周期。

       Layer類内部的成員變量mUserClientRef指向了一個ClientRef對象,這個ClientRef對象内部有一個成員變量mControlBlock,它指向了一個SharedBufferServer對象。從前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文可以知道,SharedBufferServer類是用來在SurfaceFlinger服務這一側描述一個UI中繼資料緩沖區堆棧的,即在SurfaceFlinger服務中,每一個繪圖表面,即一個Layer對象,都關聯有一個UI中繼資料緩沖區堆棧。

       LayerBaseClient類内部有一個類型為LayerBaseClient::Surface的弱指針,它引用了一個Layer::SurfaceLayer對象。這個Layer::SurfaceLayer對象是一個Binder本地對象,它是SurfaceFlinger服務用來與Android應用程式建立通信的,以便可以共同維護一個繪圖表面。

       Layer::SurfaceLayer類繼承了LayerBaseClient::Surface類,它的實作如圖2所示。

圖2 SurfaceLayer類的實作

       了解這個圖需要了解Android系統的Binder程序間通信機制,具體可以參考​​Android程序間通信(IPC)機制Binder簡要介紹和學習計劃​​一文。從這裡就可以看出,Layer::SurfaceLayer類實作了ISurface接口,而Android應用程式就是通過這個接口來和SurfaceFlinger服務共同維護一個繪圖表面的。

       Layer::SurfaceLayer類内部有兩個成員變量mFlinger和mOwner,前者指向了SurfaceFlinger服務,而後者指向了其宿主Layer對象。

       ISurface接口定義在檔案frameworks/base/include/surfaceflinger/ISurface.h中,它有一個重要的成員函數requestBuffer,如下所示:

[cpp] ​​view plain​​​​copy​​

  1. class ISurface : public IInterface  
  2. {  
  3.     ......  
  4. public:  
  5.     DECLARE_META_INTERFACE(Surface);  
  6.     /* 
  7.      * requests a new buffer for the given index. If w, h, or format are 
  8.      * null the buffer is created with the parameters assigned to the 
  9.      * surface it is bound to. Otherwise the buffer's parameters are 
  10.      * set to those specified. 
  11.      */  
  12.     virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,  
  13.             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;  
  14. };  

        Android應用程式就是通過ISurface接口的成員函數requestBuffer來請求SurfaceFlinger服務為它的一個繪圖表面配置設定一個圖形緩沖區的,這個圖形緩沖區使用一個GraphicBuffer對象來描述。

        由于Layer::SurfaceLayer是一個Binder本地對象類,是以,就相應地有一個Binder代理對象類,它的名稱為BpSurface,它的實作如圖3所示圖3 BpSurface類的實作

       了解這個圖同樣需要了解Android系統的Binder程序間通信機制,具體可以參考​​Android程序間通信(IPC)機制Binder簡要介紹和學習計劃​​一文。

       以上都是從SurfaceFlinger服務這一側來了解一個Surface,下面我們再從Android應用程式這一側來了解一個Surface。

       在Android應用程式這一側,每一個繪圖表面都使用一個Surface對象來描述,每一個Surface對象都是由一個SurfaceControl對象來建立的。Surface類和SurfaceControl類的關系以及實作如圖4所示。

圖4 Surface類和SurfaceControl類的關系以及實作

       SurfaceControl類的成員變量mClient是一個類型為SurfaceComposerClient的強指針,它指向了Android應用程式程序中的一個SurfaceComposerClient單例對象。在前面​​Android應用程式與SurfaceFlinger服務的連接配接過程分析​​一文中,我們已經看到過SurfaceComposerClient類的作用了,Android應用程式主要就是通過它來和SurfaceFlinger服務建立連接配接的,連接配接的結果就是得到一個類型為Client的Binder代理對象,儲存它的成員變量mClient中。

      SurfaceControl類的成員變量mSurface是一個類型為ISurface的強指針,它指向了一個類型為BpSurface的Binder代理對象,而這個Binder代理對象引用的是一個Layer::SurfaceLayer對象。當Android應用程式請求SurfaceFlinger服務建立一個繪圖表面的時候,SurfaceFlinger服務就會在内部建立一個Layer::SurfaceLayer對象,并且将這個Layer::SurfaceLayer對象的一個Binder代理對象傳回來給Android應用程式,然後Android應用程式再将這個Binder代理對象儲存在一個SurfaceControl對象的成員變量mSurface中。

      SurfaceControl類的成員變量mSurfaceData是一個類型為Surface的強指針,它指向了一個Surface對象。

      Surface類就是用來在Android應用程式這一側描述繪圖表面的,它的成員變量mSurface與它的宿主類SurfaceControl的成員變量mSurface指向的是同一個Binder代理對象,即它們都引用了在SurfaceFlinger服務内部所建立的一個類型為Layer::SurfaceLayer的Binder本地對象。

      Surface類的成員變量mClient指向了Android應用程式程序中的一個SurfaceClient單例對象。在前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文中,我們已經介紹過SurfaceClient類的實作了,Android應用程式就是通過它來請求SurfaceFlinger服務建立共享UI中繼資料的,并且可以通過它來請求SurfaceFlinger服務渲染一個繪圖表面。

      Surface類的成員變量mSharedBufferClient指向了一個SharedBufferClient對象。從前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文可以知道,SharedBufferClient類是用來在Android應用程式這一側描述一個UI中繼資料緩沖區堆棧的,即在Android應用程式中,每一個繪圖表面,即一個Surface對象,都關聯有一個UI中繼資料緩沖區堆棧。

      Surface類繼承了EGLNativeBase類,而EGLNativeBase類又繼承了ANativeWindow類。我們知道,Android系統是通過OpenGL庫來繪制UI的。OpenGL庫在繪制UI的時候,需要底層的系統提供一個本地視窗給它,以便它可以将UI繪制在這個本地視窗上。Android系統為OpenGL庫定提供的本地視窗使用ANativeWindow類來描述,Surface類通過EGLNativeBase類間接地繼承了ANativeWindow類,是以,Surface類也是用來描述OpenGL繪圖所需要的一個本地視窗的。從這個角度出發,我們可以将Surface類看作OpenGL庫與Android的UI系統之間的一個橋梁。

      讨論到這裡,我們就可以知道,一個繪圖表面,在SurfaceFlinger服務和Android應用程式中分别對應有一個Layer對象和一個Surface對象,這兩個對象在内部分别使用一個SharedBufferServer對象和一個SharedBufferClient對象來描述這個繪圖表面的UI中繼資料緩沖堆棧。在前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文中,我們已經分析過這個UI中繼資料的建立過程了,接下來,我們再簡要看一下SharedBufferServer類和SharedBufferClient類的定義。

      SharedBufferServer類和SharedBufferClient類均是從SharedBufferBase類繼承下來的,如圖5所示。

圖5 SharedBufferBase、SharedBufferServer和SharedBufferClient的關系

      在基類SharedBufferBase中,有三個成員變量mSharedClient、mSharedStack和mIdentity。成員變量mSharedClient指向一塊UI中繼資料緩沖區,即一個SharedClient對象;成員變量mSharedStack指向一個UI中繼資料堆棧,即一個SharedBufferStack對象;成員變量mIdentity用來描述一個繪圖表面的ID。

      在前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文提到,每一個與UI相關的Android應用程式内部都有一個唯一的SharedClient對象,這個SharedClient對象内部有一個SharedBufferStack數組surfaces,SharedBufferServer類的成員變量mSharedStack所指向的SharedBufferStack對象,正是成員變量mSharedClient所指向的一個SharedClient對象内部的一個SharedBufferStack數組的一個元素,這一點可以從SharedBufferServer類的構造函數實作來看出。

      SharedBufferServer類的構造函數frameworks/base/libs/surfaceflinger_client/SharedBufferStack.cpp檔案中,如下所示:

  1. SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,  
  2.         int surface, int32_t identity)  
  3.     : mSharedClient(sharedClient),  
  4.       mSharedStack(sharedClient->surfaces + surface),  
  5.       mIdentity(identity)  
  6. }  

       其中,參數surface表示mSharedStack指向的是mSharedClient中的SharedBufferStack數組surfaces的第幾個元素。

       在SharedBufferClient類中,有三個成員變量mNumBuffers、tail和queue_head,它們的含義可以參考前面​​Android應用程式與SurfaceFlinger服務的關系概述和學習計劃​​一文中的圖6,如下所示。圖6 SharedBufferClient眼中的SharedBufferStack 

       在Android應用程式這一側,當它需要渲染一個Surface時,它就會首先找到對應的SharedBufferClient對象,然後再調用它的成員函數dequeue來請求配置設定一個UI中繼資料緩沖區。有了這個UI中繼資料緩沖區之後,Android應用程式再調用這個SharedBufferClient對象的成員函數setDirtyRegion、setCrop和setTransform來設定對應的Surface的裁剪區域、紋理坐标以及旋轉方向。此外,Android應用程式還會請求SurfaceFlinger服務為這個Surface配置設定一個圖形緩沖區,以便可以往這個圖形緩沖區寫入實際的UI資料。最後,Android應用程式就可以調用這個SharedBufferClient對象的成員函數queue把前面已經準備好了的UI中繼資料緩沖區加入到它所描述的一個UI中繼資料緩沖區堆棧的待渲染隊列中,以便SurfaceFlinger服務可以在合适的時候對它進行渲染。這個過程我們在下一篇文章中再詳細分析。

       SharedBufferServer類的成員變量mNumBuffers的含義可以參考前面​​Android應用程式與SurfaceFlinger服務的關系概述和學習計劃​​一文中的圖7,如下所示。

圖7 SharedBufferServer眼中的SharedBufferStack

        當SurfaceFlinger服務需要渲染一個Surface的時候,它就會找到對應的一個SharedBufferServer對象,然後調用它的成員函數getQueueCount來檢查它所描述的一個UI中繼資料緩沖區堆棧的待渲染隊列的大小。如果這個大小大于0,那麼SurfaceFlinger服務就會繼續調用它的成員函數retireAndLock來取出隊列中的第一個UI中繼資料緩沖區,以及調用它的成員函數getDirtyRegion、getCrop和getTransform來獲得要渲染的Surface的裁剪區域、紋理坐标和旋轉方向。最後,SurfaceFlinger服務就可以結合這些資訊來将儲存這個Surface的圖形緩沖區中的UI資料渲染在顯示屏中。這個過程我們同樣在下一篇文章中再詳細分析。

       SharedBufferServer類的另外一個成員變量mBufferList指向了一個BufferList對象,這個BufferList對象是用來管理SharedBufferServer類所描述的一個UI中繼資料緩沖區堆棧的,接下來我們就簡要分析它的定義。

       BufferList類定義在frameworks/base/include/private/surfaceflinger/SharedBufferStack.h檔案中,如下所示:

  1. class SharedBufferServer  
  2.     : public SharedBufferBase,  
  3.       public LightRefBase<SharedBufferServer>  
  4. private:  
  5.      * BufferList is basically a fixed-capacity sorted-vector of 
  6.      * unsigned 5-bits ints using a 32-bits int as storage. 
  7.      * it has efficient iterators to find items in the list and not in the list. 
  8.     class BufferList {  
  9.         size_t mCapacity;  
  10.         uint32_t mList;  
  11.     public:  
  12.         BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX)  
  13.             : mCapacity(c), mList(0) { }  
  14.         status_t add(int value);  
  15.         status_t remove(int value);  
  16.         uint32_t getMask() const { return mList; }  
  17.         class const_iterator {  
  18.             friend class BufferList;  
  19.             uint32_t mask, curr;  
  20.             const_iterator(uint32_t mask) :  
  21.                 mask(mask), curr(__builtin_clz(mask)) {  
  22.             }  
  23.         public:  
  24.             inline bool operator == (const const_iterator& rhs) const {  
  25.                 return mask == rhs.mask;  
  26.             inline bool operator != (const const_iterator& rhs) const {  
  27.                 return mask != rhs.mask;  
  28.             inline int operator *() const { return curr; }  
  29.             inline const const_iterator& operator ++() {  
  30.                 mask &= ~(1<<(31-curr));  
  31.                 curr = __builtin_clz(mask);  
  32.                 return *this;  
  33.         };  
  34.         inline const_iterator begin() const {  
  35.             return const_iterator(mList);  
  36.         }  
  37.         inline const_iterator end() const   {  
  38.             return const_iterator(0);  
  39.         inline const_iterator free_begin() const {  
  40.             uint32_t mask = (1 << (32-mCapacity)) - 1;  
  41.             return const_iterator( ~(mList | mask) );  
  42.     };  

       BufferList類的成員變量mCapacity對應于一個UI中繼資料緩沖區堆棧的容量,即最大緩沖區個數。

       BufferList類的另外一個成員變量變量mList用來描述這個堆棧中的緩沖區哪個是空閑的,哪個是正在使用的。空閑的緩沖區對應的位為0,而正在使用的緩沖區對應的位為1。舉個例子,假如一個UI中繼資料緩沖區堆棧的大小為5,其中,第1、3、5個資料緩沖區是正在使用的,而第2、4個資料緩沖區是空閑的,那麼對應的mList的值就等于10101000 00000000 00000000 00000000。當我們需要将第2個資料緩沖區設定為正在使用時,那麼隻要調用成員函數add來将左起第2位設定為1即可,即得到mList的值就等于11101000 00000000 00000000 00000000,而當我們需要将第1個資料緩沖區設定為空閑時,那麼隻要調用成員函數remove來将左起第1位設定為0即可,即得到mList的值就等于00101000 00000000 00000000 00000000。

      在BufferList類内部定義了一個疊代器const_iterator,用來從左到右周遊一個UI中繼資料緩沖區堆棧中的正在使用或者空閑的緩沖區。仍然以前面的例子為例,當我們調用BufferList類的成員函數begin時,就可以得到一個const_iterator疊代器,沿着這個疊代器往前走,就可以依次周遊第1、3、5個正在使用的緩沖區,而當我們調用BufferList類的成員函數free_begin時,就可以得到另外一個const_iterator疊代器,沿着這個疊代器往前走,就可以依次周遊第2、4個空閑的緩沖區。

      關于Surface的概念我們就分析到這裡。從這些分析可以知道,當Android應用程式請求SurfaceFlinger服務建立一個Surface的時候,需要在SurfaceFlinger服務這一側建立一個Layer對象、一個Layer::SurfaceLayer對象和一個SharedBufferServer對象,同時又需要在Android應用程式這一側建立一個SurfaceControl對象、一個Surface對象和一個SharedBufferClient對象。

      在進一步分析Android應用程式請求SurfaceFlinger服務建立Surface的過程之前,我們首先看一下Android系統的開機動畫應用程式bootanim是如何請求SurfaceFlinger服務建立一個Surface來顯示開機動畫的。

      在前面​​Android系統的開機畫面顯示過程分析一文​​中, 我們分析Android系統的開機動畫的顯示過程,其中,開機動畫應用程式bootanim是在BootAnimation類的成員函數readyToRun中請求SurfaceFlinger服務建立一個用來顯示開機動畫的Surface的,如下所示:

  1. status_t BootAnimation::readyToRun() {    
  2.     // create the native surface    
  3.     sp<SurfaceControl> control = session()->createSurface(    
  4.             getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);    
  5.     ......    
  6.     sp<Surface> s = control->getSurface();  
  7. }    

      BootAnimation類的成員函數session傳回的是一個SurfaceComposerClient對象。有了這個SurfaceComposerClient對象之後,我們就可以調用它的成員函數createSurface來請求請求SurfaceFlinger服務在内部建立一個Layer::SurfaceLayer對象,并且将這個Layer::SurfaceLayer對象的代理對象傳回來給SurfaceComposerClient類,SurfaceComposerClient類接着就将這個Layer::SurfaceLayer代理對象封裝成一個SurfaceControl對象,并且傳回給BootAnimation類,最後BootAnimation類就可以調用這個SurfaceControl對象的成員函數getSurface來獲得一個Surface對象。

      接下來,我們就從SurfaceComposerClient類的成員函數createSurface開始描述Android應用程式請求SurfaceFlinger服務建立Surface的過程,如圖8所示。

圖8 Android應用程式請求SurfaceFlinger服務建立Surface的過程 

       這個過程可以劃分為20個步驟,接下來我們就詳細分析每一個步驟。

       Step 1. SurfaceComposerClient.createSurface

  1. sp<SurfaceControl> SurfaceComposerClient::createSurface(  
  2.         int pid,  
  3.         DisplayID display,  
  4.         uint32_t w,  
  5.         uint32_t h,  
  6.         PixelFormat format,  
  7.         uint32_t flags)  
  8.     String8 name;  
  9.     const size_t SIZE = 128;  
  10.     char buffer[SIZE];  
  11.     snprintf(buffer, SIZE, "<pid_%d>", getpid());  
  12.     name.append(buffer);  
  13.     return SurfaceComposerClient::createSurface(pid, name, display,  
  14.             w, h, format, flags);  

       這個函數定義在檔案frameworks/base/libs/surfaceflinger_client/SurfaceComposerClient.cpp檔案中。

       參數pid用來描述目前程序的PID,參數display的值等于0,表示要在第一個顯示屏上建立一個Surface,參數w和h表示要建立的Surface的寬度和高度,它們的值剛好等于第一個顯示屏的寬度和高度,參數format的值等于PIXEL_FORMAT_RGB_565,表示要建立的Surface的像素格式為PIXEL_FORMAT_RGB_565,即每一個點使用2個位元組來描述,其中,R、G和B分量分别占5位、6位和5位,參數flags是一個預設參數,它等于預設值0,表示要建立的Surface的用途。

       這個函數将參數pid格式化成一個字元串之後,再調用SurfaceComposerClient類的另外一個版本的成員函數createSurface來請求SurfaceFlinger服務建立一個Surface,如下所示:

  1.         const String8& name,  
  2.     sp<SurfaceControl> result;  
  3.     if (mStatus == NO_ERROR) {  
  4.         ISurfaceComposerClient::surface_data_t data;  
  5.         sp<ISurface> surface = mClient->createSurface(&data, pid, name,  
  6.                 display, w, h, format, flags);  
  7.         if (surface != 0) {  
  8.             result = new SurfaceControl(this, surface, data, w, h, format, flags);  
  9.     }  
  10.     return result;  

       SurfaceComposerClient類的成員變量mClient指向了一個類型為BpSurfaceComposerClient的Binder代理對象,它引用了一個類型為Client的Binder本地對象。這個類型Client的Binder本地對象是在SurfaceFlinger服務内部建立的,用來和Android應用程式建立連接配接。連接配接的過程可以參考前面​​Android應用程式與SurfaceFlinger服務的連接配接過程分析​​一文。

       SurfaceComposerClient類的成員函數createSurface調用成員變量mClient的成員函數createSurface請求SurfaceFlinger服務建立一個Surface之後,就得到了一個類型為BpSurface的Binder代理對象surface。從前面的描述可以知道,Binder代理對象surface引用了在SurfaceFlinger服務這一側的一個Layer::SurfaceLayer對象。此外,SurfaceComposerClient類的成員函數createSurface還得到了一個surface_data_t對象data,它裡面包含了剛才所建立的一個Surface的資訊,例如,寬度、高度、像素格式和ID值等。

      最後,SurfaceComposerClient類的成員函數createSurface就将SurfaceFlinger服務傳回來的Binder代理對象surface和surface_data_t對象data封裝成一個SurfaceControl對象result,并且傳回給調用者。接下來,我們首先分析SurfaceFlinger服務建立Surface的過程,接着再分析SurfaceControl對象result的封裝過程。

      Step 2. Client.createSurface

  1. sp<ISurface> Client::createSurface(  
  2.         ISurfaceComposerClient::surface_data_t* params, int pid,  
  3.         DisplayID display, uint32_t w, uint32_t h, PixelFormat format,  
  4.     return mFlinger->createSurface(this, pid, name, params,  
  5.             display, w, h, format, flags);  

      這個函數定義在檔案frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。

      Client類的成員變量mFlinger指向了SurfaceFlinger服務,是以,接下來就會調用SurfaceFlinger類的成員函數createSurface來建立一個Surface。

      Step 3. SurfaceFlinger.createSurface

  1. sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid,  
  2.         const String8& name, ISurfaceComposerClient::surface_data_t* params,  
  3.         DisplayID d, uint32_t w, uint32_t h, PixelFormat format,  
  4.     sp<LayerBaseClient> layer;  
  5.     sp<LayerBaseClient::Surface> surfaceHandle;  
  6.     if (int32_t(w|h) < 0) {  
  7.         LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",  
  8.                 int(w), int(h));  
  9.         return surfaceHandle;  
  10.     //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);  
  11.     sp<Layer> normalLayer;  
  12.     switch (flags & eFXSurfaceMask) {  
  13.         case eFXSurfaceNormal:  
  14.             if (UNLIKELY(flags & ePushBuffers)) {  
  15.                 layer = createPushBuffersSurface(client, d, w, h, flags);  
  16.             } else {  
  17.                 normalLayer = createNormalSurface(client, d, w, h, flags, format);  
  18.                 layer = normalLayer;  
  19.             break;  
  20.         case eFXSurfaceBlur:  
  21.             layer = createBlurSurface(client, d, w, h, flags);  
  22.         case eFXSurfaceDim:  
  23.             layer = createDimSurface(client, d, w, h, flags);  
  24.     if (layer != 0) {  
  25.         layer->initStates(w, h, flags);  
  26.         layer->setName(name);  
  27.         ssize_t token = addClientLayer(client, layer);  
  28.         surfaceHandle = layer->getSurface();  
  29.         if (surfaceHandle != 0) {  
  30.             params->token = token;  
  31.             params->identity = surfaceHandle->getIdentity();  
  32.             params->width = w;  
  33.             params->height = h;  
  34.             params->format = format;  
  35.             if (normalLayer != 0) {  
  36.                 Mutex::Autolock _l(mStateLock);  
  37.                 mLayerMap.add(surfaceHandle->asBinder(), normalLayer);  
  38.         setTransactionFlags(eTransactionNeeded);  
  39.     return surfaceHandle;  

       這個函數定義在檔案frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。

       第一個if語句判斷參數w和h的值是否為負數,如果是的話,那麼就直接出錯傳回了,因為建立的Surface的寬度和高度值不可能為負數。

       eFXSurfaceNormal、eFXSurfaceBlur、eFXSurfaceDim和eFXSurfaceMask是四個枚舉值,它們定義在檔案frameworks/base/include/surfaceflinger/ISurfaceComposer.h中,如下所示:

  1. class ISurfaceComposer : public IInterface  
  2.     enum { // (keep in sync with Surface.java)  
  3.         ......  
  4.         ePushBuffers        = 0x00000200,  
  5.         eFXSurfaceNormal    = 0x00000000,  
  6.         eFXSurfaceBlur      = 0x00010000,  
  7.         eFXSurfaceDim       = 0x00020000,  
  8.         eFXSurfaceMask      = 0x000F0000,  

       回到SurfaceFlinger類的成員函數createSurface中,參數flags的值等于0,是以,在接下來的switch語句中,會調用SurfaceFlinger類的成員函數createNormalSurface來在顯示屏上建立一個Layer。順便提一句,如果參數flags的值等于eFXSurfaceBlur或者eFXSurfaceDim,那麼就表示要建立的是一個模糊或者漸變的Surface,這兩種類型的Surface是在原有的一個Surface上進行建立的,用來對原來的Surface進行模糊或者漸變處理。

        前面所建立的Layer儲存在變量layer中,接下來SurfaceFlinger類的成員函數createNormalSurface會調用來另外一個成員函數addClientLayer來将它儲存在内部的一個清單中,接着再調用前面所建立的Layer的成員函數getSurface來獲得一個Layer::SurfaceLayer對象surfaceHandle。

        在将Layer::SurfaceLayer對象surfaceHandle的一個Binder代理對象傳回給Android應用程式之前,SurfaceFlinger類的成員函數createNormalSurface還會以它的一個IBinder接口為關鍵字,将前面所建立的Layer儲存在SurfaceFlinger類的成員變量mLayerMap所描述的一個Map中,這樣就可以将一個Layer::SurfaceLayer對象surfaceHandle與它的宿主Layer對象關聯起來。

        接下來,我們首先分析SurfaceFlinger類的成員函數createNormalSurface和addClientLayer的實作,接着再分析Layer的成員函數getSurface的實作,以便可以了解一個Surface的建立的過程。

        Step 4. SurfaceFlinger.createNormalSurface

  1. sp<Layer> SurfaceFlinger::createNormalSurface(  
  2.         const sp<Client>& client, DisplayID display,  
  3.         uint32_t w, uint32_t h, uint32_t flags,  
  4.         PixelFormat& format)  
  5.     // initialize the surfaces  
  6.     switch (format) { // TODO: take h/w into account  
  7.     case PIXEL_FORMAT_TRANSPARENT:  
  8.     case PIXEL_FORMAT_TRANSLUCENT:  
  9.         format = PIXEL_FORMAT_RGBA_8888;  
  10.         break;  
  11.     case PIXEL_FORMAT_OPAQUE:  
  12. #ifdef NO_RGBX_8888  
  13.         format = PIXEL_FORMAT_RGB_565;  
  14. #else  
  15.         format = PIXEL_FORMAT_RGBX_8888;  
  16. #endif  
  17.     if (format == PIXEL_FORMAT_RGBX_8888)  
  18.     sp<Layer> layer = new Layer(this, display, client);  
  19.     status_t err = layer->setBuffers(w, h, format, flags);  
  20.     if (LIKELY(err != NO_ERROR)) {  
  21.         LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));  
  22.         layer.clear();  
  23.     return layer;  

       這個函數定義在檔案frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。

       函數開頭的switch語句判斷要建立的Surface是否要使用透明色。如果要使用的話,那麼就将參數format的值修改為PIXEL_FORMAT_RGBA_8888。另一方面,如果要建立的Surface不需要使用透明色,那麼就将參數format的值修改為PIXEL_FORMAT_RGB_565或者PIXEL_FORMAT_RGBX_8888,取決于是否定義了宏NO_RGBX_8888。

      函數接下來建立了一個Layer對象,并且調用這個Layer對象的成員函數setBuffers來在内部建立一個Layer::SurfaceLayer對象,最後就将這個Layer對象傳回給調用者。

      接下來,我們首先分析Layer對象的建立過程,接着再分析Layer對象的成員函數setBuffers的實作。

      Step 5. new Layer

  1. Layer::Layer(SurfaceFlinger* flinger,  
  2.         DisplayID display, const sp<Client>& client)  
  3.     :   LayerBaseClient(flinger, display, client),  
  4.         mGLExtensions(GLExtensions::getInstance()),  
  5.         mNeedsBlending(true),  
  6.         mNeedsDithering(false),  
  7.         mSecure(false),  
  8.         mTextureManager(),  
  9.         mBufferManager(mTextureManager),  
  10.         mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false),  
  11.         mBypassState(false)  

      這個函數定義在檔案frameworks/base/services/surfaceflinger/Layer.cpp中。

      Layer類的構造函數隻是執行一些簡單的初始化工作,接下來我們再繼續分析它的進一步初始化工作,這是通過Layer類的成員函數setBuffers來實作的。

      Step 6. Layer.setBuffers

  1. status_t Layer::setBuffers( uint32_t w, uint32_t h,  
  2.                             PixelFormat format, uint32_t flags)  
  3.     // this surfaces pixel format  
  4.     PixelFormatInfo info;  
  5.     status_t err = getPixelFormatInfo(format, &info);  
  6.     if (err) return err;  
  7.     // the display's pixel format  
  8.     const DisplayHardware& hw(graphicPlane(0).displayHardware());  
  9.     uint32_t const maxSurfaceDims = min(  
  10.             hw.getMaxTextureSize(), hw.getMaxViewportDims());  
  11.     // never allow a surface larger than what our underlying GL implementation  
  12.     // can handle.  
  13.     if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {  
  14.         return BAD_VALUE;  
  15.     PixelFormatInfo displayInfo;  
  16.     getPixelFormatInfo(hw.getFormat(), &displayInfo);  
  17.     const uint32_t hwFlags = hw.getFlags();  
  18.     mFormat = format;  
  19.     mWidth  = w;  
  20.     mHeight = h;  
  21.     mReqFormat = format;  
  22.     mReqWidth = w;  
  23.     mReqHeight = h;  
  24.     mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;  
  25.     mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;  
  26.     // we use the red index  
  27.     int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);  
  28.     int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);  
  29.     mNeedsDithering = layerRedsize > displayRedSize;  
  30.     mSurface = new SurfaceLayer(mFlinger, this);  
  31.     return NO_ERROR;  

       這個函數定義在檔案frameworks/base/services/surfaceflinger/Layer.cpp中。

       參數format是一個整數值,用來描述要建立的Surface的像素格式,函數首先調用另外一個函數getPixelFormatInfo來将它轉換為一個PixelFormatInfo對象info,以便可以獲得更多的該種類型的像素格式的資訊,例如,一個像素點占多少個位元組,每個顔色分量又分别占多少位等。函數getPixelFormatInfo定義檔案frameworks/base/libs/ui/PixelFormat.cpp檔案中,有興趣的讀者可以自己研究一下。

       Layer類的成員函數graphicPlane是從父類LayerBase繼承下來,用來獲得系統的第N個顯示屏,這個成員函數最終又是通過調用SurfaceFlinger類的成員函數graphicPlane來實作的,如下所示:

  1. const GraphicPlane& LayerBase::graphicPlane(int dpy) const  
  2.     return mFlinger->graphicPlane(dpy);  

      SurfaceFlinger類的成員函數graphicPlane的實作如下示:

  1. const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const  
  2.     LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);  
  3.     const GraphicPlane& plane(mGraphicPlanes[dpy]);  
  4.     return plane;  

      SurfaceFlinger類有一個類型為DisplayHardware的數組,它的大小等于4,表示Android系統最多支援4個顯示屏,每一個顯示屏都使用一個DisplayHardware對象來描述。實際上,Android系統目前隻支援一個顯示屏,是以,在調用SurfaceFlinger類的成員函數graphicPlane的時候,傳進來的參數dpy的值都是等于0。

      回到Layer類的成員函數setBuffers中,它接下來獲得了用來描述系統第1個顯示屏的DisplayHardware對象hw,接着再調用函數getPixelFormatInfo來獲得用來描述該顯示屏的像素格式資訊的PixelFormatInfo對象displayInfo。

      Layer類的成員函數setBuffers接下來再将要建立的Surface的像素格式以及大小記錄下來,即分别将參數format、w和h的值儲存在成員變量mFormat、mWidth、mHeight和mReqFormat、mReqWidth、mReqHeight中。

      Layer類的成員函數setBuffers接下來再檢查參數flags的ISurfaceComposer::eSecure位是否等于1。如果等于1的話,就将成員變量mSecure的值設定為true,否則就設定為false。當參數flags的ISurfaceComposer::eSecure位等于1的時候,就表示正在建立的Surface的UI資料是可以安全地從一個程序拷貝到另外一個程序的。有些Surface的UI資料是不可以随便拷貝的,因為這涉及到安全問題,例如,用來建立螢幕截圖的Surface的UI資料就是不可以随便從一個程序拷貝到另外一個程序的,因為螢幕截圖可能會包含隐私資訊。

      Layer類的成員函數setBuffers接下來又檢查要建立的Surface的像素格式的Alpha通道的高8位是否大于低8位。如果是的話,就将成員變量mNeedsBlending的值設定為true,表示在渲染時要執行混合操作。

      Layer類的成員函數setBuffers接下來還檢查要建立的Surface的像素格式的Red通道的大小是否大于系統第1個顯示屏的像素格式的Red通道的大小。如果是的話,就将成員變量mNeedsDithering的值設定為true,表示在渲染時要執行抖動操作。

      最後,Layer類的成員函數setBuffers就建立了一個SurfaceLayer對象,并且儲存成員變量mSurface中。

      接下來,我們就繼續分析SurfaceLayer對象的建立過程。

      Step 7. new SurfaceLayer

  1. Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,  
  2.         const sp<Layer>& owner)  
  3.     : Surface(flinger, owner->getIdentity(), owner)  

       這個函數定義在檔案frameworks/base/services/surfaceflinger/Layer.cpp中。

       SurfaceLayer類的構造函數的實作很簡單,它隻是使用參數flinger以及owner來初始其父類Surface,其中,參數flinger指向的是SurfaceFlinger服務,而參數owner指向的是正在建立的SurfaceLayer對象的宿主Layer對象。

       這一步執行完成之後,  沿着調用路徑傳回到SurfaceFlinger類的成員函數createSurface中,這時候就建立好一個Layer對象及其内部的一個SurfaceLayer對象了,接下來,我們繼續分析SurfaceFlinger類的成員函數addClientLayer的實作,以便可以了解SurfaceFlinger服務是如何維護它所建立的Layer的,即它所建立的Surface。

       Step 8. SurfaceFlinger.addClientLayer

  1. ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,  
  2.         const sp<LayerBaseClient>& lbc)  
  3.     Mutex::Autolock _l(mStateLock);  
  4.     // attach this layer to the client  
  5.     ssize_t name = client->attachLayer(lbc);  
  6.     // add this layer to the current state list  
  7.     addLayer_l(lbc);  
  8.     return name;  

       參數client指向了一個Client對象,它是用來描述目前正在請求SurfaceFlinger服務的一個Android應用程式的;參數lbc指向的是我們在前面Step 4中所建立的一個Layer對象。函數首先調用參數client所指向的一個Client對象的成員函數attachLayer來關聯參數lbc所指向的一個Layer對象,以表示參數lbc所指向的一個Layer對象是由參數client所指向的一個Client對象所描述的一個Android應用程式請求建立的,接下來再調用SurfaceFlinger類的成員函數addLayer_l來将參數lbc所指向的一個Layer對象儲存在SurfaceFlinger的内部。

       接下來,我們首先分析Client類的成員函數attachLayer的實作,接着再分析SurfaceFlinger類的成員函數addLayer_l的實作。

       Step 9. Client.attachLayer

  1. ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer)  
  2.     int32_t name = android_atomic_inc(&mNameGenerator);  
  3.     mLayers.add(name, layer);  

       從前面​​Android應用程式與SurfaceFlinger服務的連接配接過程分析​​一文可以知道,Client類的成員變量mNameGenerator是用來生成Surface名稱的,它的初始值等于1,每當Android應用程式請求SurfaceFlinger服務為它建立一個Surface,SurfaceFlinger服務就會将對應的Client對象的成員變量mNameGenerator的值增加1,這樣就可以依次得到名稱等于1、2、3......的Surface。

       為正在建立的Surface生成好名稱name之後,Client類的成員函數attachLayer就以變量name為關鍵字,将用來描述正在建立的Surface的一個Layer對象layer儲存Client類的成員變量mLayers所描述的一個Map中。從這裡就可以知道,一個Android應用程式所建立的Surface,都儲存在與它所對應的一個Client對象的成員變量mLayers中。

      step 10. SurfaceFlinger.addLayer_l

  1. status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)  
  2.     ssize_t i = mCurrentState.layersSortedByZ.add(layer);  
  3.     return (i < 0) ? status_t(i) : status_t(NO_ERROR);  

      SurfaceFlinger類的成員變量mCurrentState指向了一個State對象,這個State對象内部有一個成員變量layersSortedByZ,它用來描述一個類型為LayerVector的向量,用來儲存SurfaceFlinger服務所建立的每一個Layer,并且這些Layer是按照Z軸坐示來排列的。這樣,SurfaceFlinger服務在渲染Surface的時候,就可以根據這個向量來計算可見性。

      這一步執行完成之後,回到SurfaceFlinger類的成員函數createSurface中,這時候SurfaceFlinger服務就将前面所建立的一個Layer對象儲存好在内部了,接下來就會調用這個Layer對象的成員函數getSurface來獲得在前面Step 6中所建立的一個SurfaceLayer對象,以便可以将它的一個Binder代理對象傳回請求Surface的Android應用程式。

      Layer類的成員函數getSurface是從父類LayerBaseClient繼承下來的,是以,接下來我們就繼續分析LayerBaseClient類的成員函數getSurface的實作。

      Step 11. LayerBaseClient.getSurface

  1. sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()  
  2.     sp<Surface> s;  
  3.     Mutex::Autolock _l(mLock);  
  4.     s = mClientSurface.promote();  
  5.     if (s == 0) {  
  6.         s = createSurface();  
  7.         mClientSurface = s;  
  8.     return s;  

       這個函數定義在檔案frameworks/base/services/surfaceflinger/LayerBase.cpp中。

       LayerBaseClient類的成員變量mClientSurface是一個類型為Surface的弱指針,它指向了一個Surface子類對象。函數首先将LayerBaseClient類的成員變量mClientSurface更新為一個強指針s。如果更新失敗,即得到的強指針的值等于0,那麼就說明要麼還沒有初始化LayerBaseClient類的成員變量mClientSurface,要麼LayerBaseClient類的成員變量mClientSurface所指向的一個Surface子類對象已經被銷毀了。在這種情況下,函數就會調用由其子類來重寫的成員函數createSurface來獲得一個Surface子類對象,并且儲存在成員變量mClientSurface中。最後再将得到的Surface子類對象傳回給調用者。弱指針更新為強指針的原理,可以參考​​Android系統的智能指針(輕量級指針、強指針和弱指針)的實作原理分析​​一文。

      在我們這個場景中,LayerBaseClient的子類即為Layer類,是以,接下來我們就繼續分析它的成員函數createSurface的實作。

      Step 12. Layer.createSurface

  1. sp<LayerBaseClient::Surface> Layer::createSurface() const  
  2.     return mSurface;  

      從前面的Step 6可以知道, Layer類的成員變量mSurface已經指向了一個SurfaceLayer對象,是以,函數就可以直接将它傳回給調用者。

      這一步執行完成之後,回到SurfaceFlinger類的成員函數createSurface中,這時候SurfaceFlinger服務就完成了Android應用程式所請求建立的Surface了,最後就會将用來描述這個Surface的一個urfaceLayer對象的一個Binder代理對象傳回Android應用程式,以便Android應用程式可以将它封裝成一個SurfaceControl對象,如前面的Step 1所示。

      接下來,我們就回到Android應用程式這一側,繼續分析SurfaceControl對象的建立過程。

      Step 13. new SurfaceControl

  1. SurfaceControl::SurfaceControl(  
  2.         const sp<SurfaceComposerClient>& client,  
  3.         const sp<ISurface>& surface,  
  4.         const ISurfaceComposerClient::surface_data_t& data,  
  5.         uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)  
  6.     : mClient(client), mSurface(surface),  
  7.       mToken(data.token), mIdentity(data.identity),  
  8.       mWidth(data.width), mHeight(data.height), mFormat(data.format),  
  9.       mFlags(flags)  

      這個函數定義在檔案frameworks/base/libs/surfaceflinger_client/Surface.cpp中。

      SurfaceControl類的構造函數的實作很簡單,它隻是對各個成員變量進行初始化,其中,我們需要重點關注的是,SurfaceControl類的成員變量mSurface指向的是一個類型為BpSurface的Binder代理對象,這個Binder代理對象引用的是由SurfaceFlinger服務所建立的一個類型為SurfaceLayer的Binder本地對象。

      這一步執行完成之後,傳回到開機動畫應用程式bootanim中,即BootAnimation類的成員函數readyToRun中,接下來它就會調用在這一步所建立的SurfaceControl對象的成員函數getSurface來獲得一個Surface對象。

      接下來,我們就繼續分析SurfaceControl類的成員函數getSurface的實作。

      Step 14. SurfaceControl.getSurface

  1. sp<Surface> SurfaceControl::getSurface() const  
  2.     if (mSurfaceData == 0) {  
  3.         mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));  
  4.     return mSurfaceData;  

      SurfaceControl類的成員函數getSurface第一次被調用時,成員變量mSurfaceData的值等于0,是以,函數接下來就會建立一個Surface對象,并且儲存在成員變量mSurfaceData中。

      接下來,我們就繼續分析Surface對象的建立過程。

      Step 15. new Surface

  1. Surface::Surface(const sp<SurfaceControl>& surface)  
  2.     : mBufferMapper(GraphicBufferMapper::get()),  
  3.       mClient(SurfaceClient::getInstance()),  
  4.       mSharedBufferClient(NULL),  
  5.       mInitCheck(NO_INIT),  
  6.       mSurface(surface->mSurface),  
  7.       mIdentity(surface->mIdentity),  
  8.       mFormat(surface->mFormat), mFlags(surface->mFlags),  
  9.       mWidth(surface->mWidth), mHeight(surface->mHeight)  
  10.     init();  

       這個函數定義在檔案frameworks/base/libs/surfaceflinger_client/Surface.cpp中。

       Surface類的成員變量mBufferMapper指向了一個GraphicBufferMapper對象,它是用來将配置設定到的圖形緩沖區映射到Android應用程式程序的位址空間的,在接下來的一篇文章介紹Surface的渲染過程時,我們再詳細分析。

       Surface類的成員變量mClient指向了Android應用程式程序中的一個SurfaceClient單例。從前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文可以知道,這個SurfaceClient單例是有來建立Android應用程式與SurfaceFlinger服務的共享UI中繼資料的。當SurfaceClient類的成員函數getInstance第一次在程序中被調用時,Android應用程式便會請求SurfaceFlinger服務建立這塊共享UI中繼資料。

       Surface類的成員變量mSharedBufferClient指向了一個SharedBufferClient對象。文章開始時提到,SharedBufferClient是用來在Android應用程式這一側描述一個Surface的UI中繼資料緩沖區堆棧的,後面我們再分析它的建立過程。

       Surface類的成員變量mSurface指向了一個類型為BpSurface的Binder代理對象。從Surface類的構造函數就可以看出,這個Binder代理對象引用的是在前面Step 6中建立的一個SurfaceLayer對象。

       Surface類的其餘成員變量mIdentity、mFormat、mFlags、mWidth和mHeight分别用來描述一個Surface的ID、像素格式、用途、寬度和高度。

       Surface類的構造函數接下來調用另外一個成員函數init進一步執行初始化的工作,接下來,我們就繼續分析Surface類的成員函數init的實作。

       Step 16. Surface.init

  1. void Surface::init()  
  2.     ANativeWindow::setSwapInterval  = setSwapInterval;  
  3.     ANativeWindow::dequeueBuffer    = dequeueBuffer;  
  4.     ANativeWindow::cancelBuffer     = cancelBuffer;  
  5.     ANativeWindow::lockBuffer       = lockBuffer;  
  6.     ANativeWindow::queueBuffer      = queueBuffer;  
  7.     ANativeWindow::query            = query;  
  8.     ANativeWindow::perform          = perform;  
  9.     DisplayInfo dinfo;  
  10.     SurfaceComposerClient::getDisplayInfo(0, &dinfo);  
  11.     const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;  
  12.     const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;  
  13.     // FIXME: set real values here  
  14.     const_cast<int&>(ANativeWindow::minSwapInterval) = 1;  
  15.     const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;  
  16.     const_cast<uint32_t&>(ANativeWindow::flags) = 0;  
  17.     mNextBufferTransform = 0;  
  18.     mConnected = 0;  
  19.     mSwapRectangle.makeInvalid();  
  20.     mNextBufferCrop = Rect(0,0);  
  21.     // two buffers by default  
  22.     mBuffers.setCapacity(2);  
  23.     mBuffers.insertAt(0, 2);  
  24.     if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {  
  25.         int32_t token = mClient.getTokenForSurface(mSurface);  
  26.         if (token >= 0) {  
  27.             mSharedBufferClient = new SharedBufferClient(  
  28.                     mClient.getSharedClient(), token, 2, mIdentity);  
  29.             mInitCheck = mClient.getSharedClient()->validate(token);  

       這個函數的初始化工作分為兩部分。

       第一部分初始化工作是與OpenGL庫相關的,主要就是設定OpenGL指定的一系列回調接口,以及設定裝置顯示屏資訊。前面提到,Surface類是從ANativeWindow類繼承下來的,作為OpenGL庫與Android系統的本地視窗的連接配接橋梁。

       ANativeWindow類定義了setSwapInterval、dequeueBuffer、cancelBuffer、lockBuffer、queueBuffer、query和perform一共7個回調接口,它們分别被設定為Surface類的靜态成員函數setSwapInterval、dequeueBuffer、cancelBuffer、lockBuffer、queueBuffer、query和perform。我們主要關注dequeueBuffer和queueBuffer兩個回調接口,前者用來從UI中繼資料緩沖區堆棧中獲得一個緩沖區,而後者用來将一個緩沖區插入到UI中繼資料緩沖區堆棧的待渲染隊列中。在接下來的一篇文章介紹Surface的渲染過程時,我們再詳細分析這兩個回調接口。

      ANativeWindow類還定義了四個成員變量xdpi、ydpi、minSwapInterval、maxSwapInterval和flags,這幾個成員變量也是要由Surface類來初始化的。成員變量xdpi和ydpi用來描述裝置顯示度的密度,即每英寸點數。裝置顯示屏的密碼資訊可以通過調用SurfaceComposerClient類的靜态成員函數getDisplayInfo來獲得。成員變量minSwapInterval和maxSwapInterval用來描述前後兩個緩沖區進行交換的最小和最大時間間隔。成員變量flags用來描述一些标志資訊。

      第二部分初始化工作是與UI中繼資料緩沖區相關。

      Surface類的成員變量mNextBufferTransform、mSwapRectangle和mNextBufferCrop分别用來描述下一個要渲染的圖形緩沖區的旋轉方向、裁剪區域和紋理坐标。

      Surface類的成員變量mBuffers用來描述一個類型為sp<GraphicBuffer>的Vector,主要是用來儲存一個Surface所使用的圖形緩沖區(GraphicBuffer)的。一開始的時候,這個向量的大小被設定為2,後面會根據實際需要來增加容量。

      Surface類的成員變量mSharedBufferClient指向了一個SharedBufferClient對象,用來描述一個UI中繼資料緩沖區堆棧,它的建立過程是最重要的,是以,接下來我們就詳細分析這個過程。

      Surface類的成員函數init首先調用成員變量mClient的成員函數getTokenForSurface來獲得成員變量mSurface所描述的一個Surface的token值。有了這個token值之後,接下就可以建立一個SharedBufferClient對象,并且儲存在 Surface類的成員變量mSharedBufferClient中了。

      在前面的Step 15中提到,Surface類的成員變量mClient指向的是一個SurfaceClient對象,是以,接下來我們首先分析SurfaceClient類的成員函數getTokenForSurface的實作,接着再分析SharedBufferClient對象的建立過程。

      從前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文可以知道,SurfaceClient類的成員函數getTokenForSurface實際上是調用了其成員變量mClient所指向的一個類型為BpSurfaceComposerClient的Binder代理對象的成員函數getTokenForSurface來請求SurfaceFlinger服務傳回一個Surface的token值。由于這個Binder代理對象引用的是一個類型為UserClient的Binder本地對象,這個Binder本地對象是運作在SurfaceFlinger服務這一側的。接下來,我們就直接分析UserClient類的成員函數getTokenForSurface的實作。

      Step 17. UserClient.getTokenForSurface

  1. ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const  
  2.     int32_t name = NAME_NOT_FOUND;  
  3.     sp<Layer> layer(mFlinger->getLayer(sur));  
  4.     if (layer == 0) return name;  
  5.     // if this layer already has a token, just return it  
  6.     name = layer->getToken();  
  7.     if ((name >= 0) && (layer->getClient() == this))  
  8.         return name;  
  9.     name = 0;  
  10.     do {  
  11.         int32_t mask = 1LU<<name;  
  12.         if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {  
  13.             // we found and locked that name  
  14.             status_t err = layer->setToken(  
  15.                     const_cast<UserClient*>(this), ctrlblk, name);  
  16.             if (err != NO_ERROR) {  
  17.                 // free the name  
  18.                 android_atomic_and(~mask, &mBitmap);  
  19.                 name = err;  
  20.         if (++name >= SharedBufferStack::NUM_LAYERS_MAX)  
  21.             name = NO_MEMORY;  
  22.     } while(name >= 0);  
  23.     //LOGD("getTokenForSurface(%p) => %d (client=%p, bitmap=%08lx)",  
  24.     //        sur->asBinder().get(), name, this, mBitmap);  

       從前面的調用過程可以知道,參數sur指向了一個SurfaceLayer對象,并且這個SurfaceLayer對象是在前面的Step 6中建立的。

       UserClient類的成員變量mFlinger指向了SurfaceFlinger服務,函數首先調用它的成員函數getLayer來獲得參數sur所指向的SurfaceLayer對象的宿主Layer對象layer,接着調用這個Layer對象layer的成員函數getToken來獲得它的token值。如果這個token值大于等于0,那麼就說明已經為Layer對象layer配置設定過token值了,即已經為參數sur所描述的Surface配置設定過token值了。在這種情況下,就直接将該token值傳回給Android應用程式。否則的話,UserClient類的成員函數getTokenForSurface接下來就需要為參數sur所描述的Surface配置設定一個token值。

       UserClient類的成員變量mBitmap是一個int32_t值,它是用來為Android應用程式的Surface配置設定Token值的,即如果它的第n位等于1,那麼就表示值等于n的Token已經被配置設定出去使用了。UserClient類的成員函數getTokenForSurface使用一個while循環來在成員變量mBitmap中從低位到高位找到一個值等于0的位,接着再将位所在的位置值作為參數sur所描述的一個Surface的token值,最後還會将這個token值設定到Layer對象layer裡面去,這是通過調用Layer類的成員函數setToken來實作的。

      接下來,我們就繼續分析Layer類的成員函數setToken的實作。

      Step 18. Layer.setToken

  1. status_t Layer::setToken(const sp<UserClient>& userClient,  
  2.         SharedClient* sharedClient, int32_t token)  
  3.     sp<SharedBufferServer> lcblk = new SharedBufferServer(  
  4.             sharedClient, token, mBufferManager.getDefaultBufferCount(),  
  5.             getIdentity());  
  6.     status_t err = mUserClientRef.setToken(userClient, lcblk, token);  
  7.     LOGE_IF(err != NO_ERROR,  
  8.             "ClientRef::setToken(%p, %p, %u) failed",  
  9.             userClient.get(), lcblk.get(), token);  
  10.     if (err == NO_ERROR) {  
  11.         // we need to free the buffers associated with this surface  
  12.     return err;  

       參數userClient指向了一個UserClient對象,而參數sharedClient指向了該UserClient對象内部的成員變量ctrlblk所指向的一個SharedClient對象。從前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文可以知道,這個SharedClient對象是用來描述一組UI中繼資料緩沖區堆棧的。

       Layer類的成員變量mBufferManager指向了一個BufferManager對象,通過調用它的成員函數getDefaultBufferCount就可以獲得一個UI中繼資料緩沖區堆棧的大小,即這個堆棧裡面所包含的UI中繼資料緩沖區的個數。有了這些資訊之後,Layer類的成員函數setToken就可以建立一個SharedBufferServer對象lcblk了,并且會将這個SharedBufferServer對象lcblk儲存在Layer類的成員變量mUserClientRef所描述的一個ClientRef對象的内部。這是通過調用ClientRef類的成員函數setToken來實作的,如下所示:

  1. status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,  
  2.         const sp<SharedBufferServer>& sharedClient, int32_t token) {  
  3.     { // scope for strong mUserClient reference  
  4.         sp<UserClient> userClient(mUserClient.promote());  
  5.         if (mUserClient != 0 && mControlBlock != 0) {  
  6.             mControlBlock->setStatus(NO_INIT);  
  7.     mUserClient = uc;  
  8.     mToken = token;  
  9.     mControlBlock = sharedClient;  

      這個函數同樣是定義在檔案frameworks/base/services/surfaceflinger/Layer.cpp中。

      ClientRef類有三個成員變量mUserClient、mToken和mControlBlock。其中,mUserClient是一個類型為UserClient的弱指針,它指向了參數uc所描述的一個UserClient對象,mToken是一個int32_t值,用來描述它的宿主Layer對象的token值,mControlBlock是一個類型為SharedBufferServer強指針,它指向了參數sharedCient所描述一個haredBufferServer對象,用來在SurfaceFlinger服務這一側描述一個UI中繼資料緩沖區堆棧。

     回到Layer類的成員函數setToken中,接下來我們繼續分析一個SharedBufferServer對象的建立過程。

     Step 19. new SharedBufferServer

  1. SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,  
  2.         int surface, int num, int32_t identity)  
  3.     : SharedBufferBase(sharedClient, surface, identity),  
  4.       mNumBuffers(num)  
  5.     mSharedStack->init(identity);  
  6.     mSharedStack->token = surface;  
  7.     mSharedStack->head = num-1;  
  8.     mSharedStack->available = num;  
  9.     mSharedStack->queued = 0;  
  10.     mSharedStack->reallocMask = 0;  
  11.     memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers));  
  12.     for (int i=0 ; i<num ; i++) {  
  13.         mBufferList.add(i);  
  14.         mSharedStack->index[i] = i;  

       這個函數定義在檔案frameworks/base/libs/surfaceflinger_client/SharedBufferStack.cpp中。

       SharedBufferServer類的構造函數主要是用來初始它所描述的一個UI中繼資料緩沖區堆棧的,這個UI中繼資料緩沖區堆棧是通過其父類的成員變量mSharedStack所指向的一個SharedBufferStack對象來描述的。SharedBufferStack類的各個成員變量的含義可以參考前面前面​​Android應用程式與SurfaceFlinger服務之間的共享UI中繼資料(SharedClient)的建立過程分析​​一文,這裡不再複述。

       這一步執行完成之後,沿着調用路徑,一直傳回到前面的Step 16中,即Surface類的成員函數init中,這時候Android應用程式就獲得了正在建立的Surface的token值,接下來就可以以這個token值為參數,來建立一個SharedBufferClient對象了。

       Step 20. new SharedBufferClient

  1. SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,  
  2.       mNumBuffers(num), tail(0)  
  3.     SharedBufferStack& stack( *mSharedStack );  
  4.     tail = computeTail();  
  5.     queued_head = stack.head;  

       這個函數定義在檔案frameworks/base/libs/surfaceflinger_client/SharedBufferStack.cpp中。