Android圖形系統(六)-app與SurfaceFlinger服務連線過程
經過上一篇的概覽,我們對Android圖形系統渲染流程有了一個大致的瞭解,這篇開始做細節分析。那麼先來總結下app與SurfaceFlinger服務連線過程。
經過前面的activity 、window 、view 的分析我們大致瞭解了Activity的顯示過程。其實Surface的建立過程與Activity的顯示過程密不可分。
那麼就從Activity.makeVisible 開始捋下流程:
1 Activity.makeVisible getWindowManager() 並執行addView。
2 經過WindowManagerImpl 和 WindowManagerGlobal addView , 最終建立了ViewRootImpl
3 ViewRootImpl 內部會new Surface() ,它是一個Parcelable物件,可在程序間傳遞,但目前僅是一個空殼,還未被賦值。
同時,通過WindowManagerGlobal.getWindowSession()獲取了Session例項,準備好了與WMS通訊,並且Session內有個成員變數SurfaceSession值得關注,它的初始化是在Session的windowAddedLocked方法,先埋個伏筆。
4 根據流程我們知道,最終ViewRootImpl會在走setView, 在這個方法中開始了兩個流程:
requestLayout() 開啟了繪製流程。 mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mInputChannel);binder ipc 讓WMS執行新增並顯示window操作。
我們先來看看mWindowSession.addToDisplay,這個過程最終是在WMS執行addWindow方法:
addWindow(…){ ... //建立 WindowState, WindowState是系統層面對Window管理的一個封裝類,與Window一一對應的。 WindowState win = new WindowState(...); … //別的都不看了,重點關注attach方法 win.attach(); ... } //WindowState.java void attach() { mSession.windowAddedLocked();//mSession 是 Session }
我們之前埋過伏筆的,windowAddedLocked建立了SurfaceSession 物件,並將當前 Session 新增到 WMS.mSessions 成員變數。SurfaceSession 的建立會呼叫 JNI,在 JNI 呼叫 nativeCreate()。
從這裡開始要細說下了,這是應用程式與SurfaceFlinger建立連線的關鍵點:
跟蹤到android_view_SurfaceSession.cpp 的nativeCreate()方法,建立了SurfaceComposerClient 物件,並且將這個物件賦值給型別為sp<SurfaceComposerClient>的智慧指標mSession時,就會導致SurfaceComposerClient類的成員函式onFirstRef被呼叫:
void SurfaceComposerClient::onFirstRef() { sp<ISurfaceComposer> sm(ComposerService::getComposerService()); if (sm != 0) { sp<ISurfaceComposerClient> conn = sm->createConnection(); if (conn != 0) { mClient = conn; mStatus = NO_ERROR; } } }
SurfaceComposerClient類的成員函式getComposerService用來獲得SurfaceFlinger服務的一個代理介面.
sp<ISurfaceComposer> ComposerService::getComposerService() { return ComposerService::getInstance().mComposerService; }
ComposerService類是單例模式,當我們第一次呼叫它的靜態函式getInstance的時候,它就會在建構函式中獲得SurfaceFlinger服務的一個代理介面,並且儲存在它的成員變數mComposerService中,同時會通過這個代理介面的成員函式getCblk來獲得一塊匿名共享記憶體mServerCblkMemory。這塊匿名共享記憶體是由SurfaceFlinger服務建立的,用來描述系統顯示屏的資訊,例如,顯示屏的個數、大小、方向、密度等等資訊。
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()); }
這時候sm有值了,在接著onFirstRef()往下執行:
sp<ISurfaceComposerClient> conn = sm->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; }
是不是感覺特別繞,下面來簡單總結下:
首先ComPoserService作為client 與 SurfaceFlinger server進行binder IPC , 獲取到SurfaceFlinger建立的Client物件,它相當於是SurfaceFlinger內部對應用程式客戶端的封裝物件,而Client與SurfaceComposerClient又互為binder ipc的兩端,SurfaceComposerClient為client端,Client為server端。

這樣,應用程序成功通過SurfaceComposerClient與SurfaceFlinger建立了連線。
下篇分析app請求SurfaceFlinger建立Surface過程。