Android應用程式與SurfaceFlinger服務的串連過程分析

來源:互聯網
上載者:User

        前文在描述Android應用程式和SurfaceFlinger服務的關係時提到,每一個有UI的Android應用程式都需要與SurfaceFlinger服務建立一個串連,以便可以通過這個串連來請求SurfaceFlinger服務為它建立和渲染Surface。在本文中,我們將以Android系統的開機動畫應用程式為例,詳細描述Android應用程式是如何與SurfaceFlinger服務建立串連的。

        Android系統的開機動畫是由應用程式bootanimation來實現的,它位於/system/bin目錄下,它的具體實現可以參考Android系統的開機畫面顯示過程分析一文。為什麼要選擇Android系統的開機動畫來分析Android應用程式與SurfaceFlinger服務的串連過程呢?首先,負責實現開機動畫的應用程式bootanimation也是一個Android應用程式,只不過它是使用C++語言來開發的;其次,應用程式bootanimation是與UI相關的,即它與使用Java語言來開發的標準Android應用程式一樣,都需要使用SurfaceFlinger服務來建立和渲染自己的Surface,即開機動畫;第三,由於應用程式bootanimation不涉及使用者輸入,即不需要與使用者進行互動(觸控螢幕、鍵盤等),因此它能夠以最簡潔的方式來體現Android應用程式與SurfaceFlinger服務的關係。

        從前面Android系統的開機畫面顯示過程分析一文可以知道,Android系統的開機動畫是主要一個BootAnimation對象來實現,這個BootAnimation對象在構造的時候,會在內部建立一個SurfaceComposerClient對象來負責建立一個到SurfaceFlinger服務的串連。

        BootAnimation類的建構函式實現在檔案frameworks/base/cmds/bootanimation/BootAnimation.cpp中,如下所示:

BootAnimation::BootAnimation() : Thread(false){    mSession = new SurfaceComposerClient();}

        mSession是BootAnimation類的成員變數,它是一個類型為SurfaceComposerClient的強指標,即sp<SurfaceComposerClient>。Android系統的智能指標的相關知識,可以參考Android系統的智能指標(輕量級指標、強指標和弱指標)的實現原理分析一文。

        在SurfaceComposerClient類內部,有一個類型為sp<ISurfaceComposerClient>的成員變數mClient,1所示:

圖1 SurfaceComposerClient的結構

        SurfaceComposerClient類的成員變數mClient指向的實際上是一個類型為BpSurfaceComposerClient的Binder代理對象,而這個類型為BpSurfaceComposerClient的Binder代理對象引用的是一個類型為Client的Binder本機物件。在前面Android應用程式與SurfaceFlinger服務的關係概述和學習計劃一文中提到,類型為Client的Binder本機物件是由SurfaceFlinger服務來負責建立的,並且運行在SurfaceFlinger服務中,用來代表使用SurfaceFlinger服務的一個用戶端,即一個與UI相關的Android應用程式。

        由於Client類和BpSurfaceComposerClient類分別是一個Binder本機物件類和一個Binder代理對象類,它們都是根據Android系統在應用程式架構層提供的Binder處理序間通訊庫來實現的,它們的實現結構圖分別2和圖3所示:

圖2 Client類的實現結構圖

圖3 BpSurfaceComposerClient類的實現結構圖

        在圖2和圖3中,涉及到了比較多的Binder處理序間通訊庫的類,需要讀者對Android系統的Binder處理序間通訊機制有一定的理解和認識。在前面的Android處理序間通訊(IPC)機制Binder簡要介紹和學習計劃一系列文章,我們已經學習過Android系統的Binder處理序間通訊機制了,這裡不再詳述。        圖2和圖3給我們最重要的資訊是Client類和BpSurfaceComposerClient類均實現了類型為ISurfaceComposerClient的Binder介面。ISurfaceComposerClient介面有兩個重要的成員函數getControlBlock和createSurface,它們定義在檔案frameworks/base/include/surfaceflinger/ISurfaceComposerClient.h中,如下所示:
class ISurfaceComposerClient : public IInterface{public:    ......    virtual sp<IMemoryHeap> getControlBlock() const = 0;    ......    /*     * Requires ACCESS_SURFACE_FLINGER permission     */    virtual sp<ISurface> createSurface( surface_data_t* data,                                        int pid,                                        const String8& name,                                        DisplayID display,                                        uint32_t w,                                        uint32_t h,                                        PixelFormat format,                                        uint32_t flags) = 0;    ......};

       其中,成員函數getControlBlock用來獲得由SurfaceFlinger服務建立的一塊用來傳遞UI中繼資料的匿名共用記憶體,而成員函數createSurface用來請求SurfaceFlinger服務建立一個Surface。從前面Android應用程式與SurfaceFlinger服務的關係概述和學習計劃一文可以知道,用來傳遞UI中繼資料的匿名共用記憶體最終會被結構化為一個SharedClient對象,這個SharedClient對象在每個應用程式進程中至多存在一個。在接下來的兩篇文章中,我們再詳細分析ISurfaceComposerClient介面的成員函數getControlBlock和createSurface的實現。       理解了SurfaceComposerClient、Client以及BpSurfaceComposerClient這三個類的關係之後,接下來我們就可以分析Android系統的開機動畫應用程式bootanimation是如何與SurfaceFlinger服務建立串連的。       從圖1可以知道,SurfaceComposerClient類繼承了RefBase類,因此,當BootAnimation類在建構函式建立了一個SurfaceComposerClient對象,並且將這個對象賦值給類型為sp<SurfaceComposerClient>的智能指標mSession時,就會導致SurfaceComposerClient類的成員函數onFirstRef被調用,而SurfaceComposerClient類的成員函數onFirstRef在調用的過程中,就會在應用程式bootanimation與SurfaceFlinger服務建立一個串連,這個過程4所示:圖4 Android應用程式與SurfaceFlinger服務的串連過程        接下來,我們就詳細分析每一個步驟。        Step 1. SurfaceComposerClient::onFirstRef

void SurfaceComposerClient::onFirstRef(){    sp<ISurfaceComposer> sm(getComposerService());    if (sm != 0) {        sp<ISurfaceComposerClient> conn = sm->createConnection();        if (conn != 0) {            mClient = conn;            ......            mStatus = NO_ERROR;        }    }}

       SurfaceComposerClient類的成員函數onFirstRef實現在檔案frameworks/base/libs/surfaceflinger_client/SurfaceComposerClient.cpp檔案中。

       SurfaceComposerClient類的成員函數getComposerService用來獲得SurfaceFlinger服務的一個代理介面,它的實現如下所示:
sp<ISurfaceComposer> ComposerService::getComposerService() {    return ComposerService::getInstance().mComposerService;}

        ComposerService類是單例模式,當我們第一次調用它的靜態函數getInstance的時候,它就會在建構函式中獲得SurfaceFlinger服務的一個代理介面,並且儲存在它的成員變數mComposerService中,如下所示:

ComposerService::ComposerService(): Singleton<ComposerService>() {    const String16 name("SurfaceFlinger");    while (getService(name, &mComposerService) != NO_ERROR) {        usleep(250000);    }    mServerCblkMemory = mComposerService->getCblk();    mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(            mServerCblkMemory->getBase());}

       在ComposerService類的建構函式中,除了會獲得SurfaceFlinger服務的代理介面之外,還會通過這個代理介面的成員函數getCblk來獲得一塊匿名共用記憶體mServerCblkMemory。這塊匿名共用記憶體是由SurfaceFlinger服務建立的,用來描述系統顯示屏的資訊,例如,顯示屏的個數、大小、方向、密度等等資訊。由於這些資訊可以通過一個surface_flinger_cblk_t對象來描述,因此,ComposerService類的建構函式最後就將前面從SurfaceFlinger服務獲得的一塊匿名共用記憶體結構化為一個surface_flinger_cblk_t對象,並且儲存在ComposerService類的成員變數mServerCblk中。

       回到SurfaceComposerClient類的成員函數onFirstRef中,由於SurfaceFlinger服務實現了ISurfaceComposer介面,因此,我們可以將前面獲得的SurfaceFlinger服務的代理介面賦值給一個類型為ISurfaceComposer的強指標sm,並且調用它的成員函數createConnection來請求SurfaceFlinger服務建立一個串連,即建立一個類型為Client的Binder對象,並且將這個Binder對象的一個代理介面conn返回來。SurfaceComposerClient類獲得了SurfaceFlinger服務返回來的Client代理介面conn之後,就將它儲存自己的成員變數mClient中,這樣開機動畫應用程式bootanimation後續就可以通過它來請求SurfaceFlinger建立和渲染Surface了。       接下來,我們就繼續分析SurfaceFlinger服務的成員函數createConnection的實現,以便可以瞭解它是如何為Android應用程式建立一個串連的。       Step 2. SurfaceFlinger::createConnection
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection(){    sp<ISurfaceComposerClient> bclient;    sp<Client> client(new Client(this));    status_t err = client->initCheck();    if (err == NO_ERROR) {        bclient = client;    }    return bclient;}

        SurfaceFlinger類的成員函數createConnection實現在檔案frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中,它的實現很簡單,只是建立了一個類型為Client的Binder對象client,並且獲得它的一個ISurfaceComposerClient介面,最後將這個ISurfaceComposerClient介面,即一個Client代理對象,返回給開機動畫應用程式bootanimation。

        接下來,我們再繼續分析Client對象的建立過程,,即Client類的建構函式的實現。        Step 3. new Client
Client::Client(const sp<SurfaceFlinger>& flinger)    : mFlinger(flinger), mNameGenerator(1){}

        Client類有兩個成員變數mFlinger和mNameGenerator,它們的類型分別為sp<SurfaceFlinger>和int32_t,前者指向了SurfaceFlinger服務,而後者用來產生SurfaceFlinger服務為Android應用程式所建立的每一個Surface的名稱。例如,假設一個Android應用程式請求SurfaceFlinger建立了兩個Surface,那麼第一個Surface的名稱就由數字1來描述,而第二個Surface就由數字2來描述,依次類推。從前面Android應用程式與SurfaceFlinger服務的關係概述和學習計劃這篇文章可以知道,一個Android應用程式最多可以建立31個Surface。        回到SurfaceFlinger類的成員函數createConnection中,它將一個指向了一個Client對象的ISurfaceComposerClient介面返回到開機動畫應用程式bootanimation之後,開機動畫應用程式bootanimation就可以將它封裝成一個類型為BpSurfaceComposerClient的Binder代理對象。        Step 4. return BpSurfaceComposerClient        類型為BpSurfaceComposerClient的Binder代理對象的封裝過程實現在SurfaceFlinger服務的Binder代理對象類BpSurfaceComposer的成員函數createConnection中,如下所示:

class BpSurfaceComposer : public BpInterface<ISurfaceComposer>{public:    ......    virtual sp<ISurfaceComposerClient> createConnection()    {        uint32_t n;        Parcel data, reply;        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());        remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);        return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());    }    ......}

        interface_cast是一個模板函數,它定義在framework/base/include/binder/IInterface.h檔案中:

template<typename INTERFACE>  inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)  {      return INTERFACE::asInterface(obj);  }  

        從這裡就可以看出,當模板參數為ISurfaceComposerClient的時候,模板函數interface_cast實際就是通過調用ISurfaceComposerClient類的靜態成員函數asInterface來將參數obj所描述的一個Binder代理對象,即一個BpBinder對象,封裝成一個BpSurfaceComposerClient對象。

        ISurfaceComposerClient類的靜態成員函數asInterface是由frameworks/base/libs/surfaceflinger_client/ISurfaceComposerClient.cpp檔案中的IMPLEMENT_META_INTERFACE宏來定義的,如下所示:
IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");

       

       IMPLEMENT_META_INTERFACE宏展開後,得到ISurfaceComposerClient類的靜態成員函數asInterface的實現如下所示:
android::sp<ISurfaceComposerClient> ISurfaceComposerClient::asInterface(const android::sp<android::IBinder>& obj)       {                                                                                           android::sp<ISurfaceComposerClient> intr;                                                                if (obj != NULL) {                                                                               intr = static_cast<ISurfaceComposerClient*>(                                                                        obj->queryLocalInterface(ISurfaceComposerClient::descriptor).get());                    if (intr == NULL) {                              intr = new BpSurfaceComposerClient(obj);                                                  }                                                }      return intr;                                    }     

        參數obj是從BpSurfaceComposer類的成員函數createConnection傳進來的,它指向的實際上是一個BpBinder對象。當我們調用一個BpBinder對象的成員函數queryLocalInterface時,獲得的是一個NULL指標,因此,ISurfaceComposerClient類的靜態成員函數asInterface最後就會將參數obj所指向的一個BpBinder對象封裝成一個BpSurfaceComposerClient對象,並且返回給調用者。

        BpSurfaceComposerClient對象的更具體封裝過程可以參考前面淺談Android系統處理序間通訊(IPC)機制Binder中的Server和Client獲得Service Manager介面之路一文中所描述的BpServiceManager對象的封裝過程。        至此,開機動畫應用程式bootanimation就通過SurfaceComposerClient類來與SurfaceFlinger服務建立一個串連了。        在前面Android應用程式與SurfaceFlinger服務的關係概述和學習計劃一文中提到,一個Android應用程式除了需要與SurfaceFlinger服務建立串連之外,還需要有一塊用來傳遞UI中繼資料的匿名共用記憶體,即一個SharedClient對象,因此,在接下來的一篇文章中,我們就繼續分析這塊匿名共用記憶體的建立過程,敬請期待! 老羅的新浪微博:http://weibo.com/shengyangluo,歡迎關注!
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.