Android 的圖形系統是 Client-Server 架構, Server 是 SurfaceFlinger, Client 則是應用程式.
應用程式第一次執行時, Window
Management Service (WMS) 會開啟一個 session,
openSession()函式會被調用. openSession()函式在BSP的位置和程式代碼如下:
\frameworks\base\services\java\com\android\server\WindowManagerService.java
01 public IWindowSession openSession(IInputMethodClient client, 02 IInputContext inputContext) { 03 04 if (client == null) 05 throw new IllegalArgumentException("null client"); 06 if (inputContext == null) 07 throw new IllegalArgumentException("null inputContext"); 08 return new Session(client, inputContext); 09 }
根據筆者的實驗, 若是該程式的 process 沒有被 kill, 則不論重複執行幾次, 都不會再調用openSession.
在建立 Session 物件時, 會透過 JNI 調用 SurfaceSession_init()
函式.程式碼如下:
\frameworks\base\core\jni\android_view_Surface.cpp
01 static void SurfaceSession_init(JNIEnv* env, jobject clazz) 02 { 03 sp<SurfaceComposerClient> client = new SurfaceComposerClient; 04 client->incStrong(clazz); 05 env->SetIntField(clazz, sso.client, (int)client.get()); 06 }
SurfaceSession_init() 函式執行了一個重要的工作 : 建立 SurfaceComposerClient 物件. 這個物件的誕生, 背後會引發一串精采的過程. 本文的目的就在說明這些過程.
SurfaceComposerClient的無參建構式會執行兩個重要工作:
1.
透過 Service
Manager 取得 surfaceflinger
service的資訊, 並且使用 binder 和 surfaceflinger service 所在的 process 建立通信管道.
2.
調用
surfaceflinger的 createConnection()取得ISurfaceFlingerClient 介面.
最後, 將 SurfaceComposerClient 的實例返回 java 層. 接者, 我們要看class SurfaceComposerClient 的無參建構式, 程式代碼如下:
\frameworks\base\libs\surfaceflinger_client\SurfaceComposerClient.cpp
01 SurfaceComposerClient::SurfaceComposerClient() 02 { 03 sp<ISurfaceComposer> sm(getComposerService()); 04 if (sm == 0) { 05 _init(0, 0); 06 return; 07 } 08 09 _init(sm, sm->createConnection()); 10 11 if (mClient != 0) { 12 Mutex::Autolock _l(gLock); 13 VERBOSE("Adding client %p to map", this); 14 gActiveConnections.add(mClient->asBinder(), this); 15 } 16 }
建構式中第一個重要工作是調用getComposerService()函式, 程式代碼如下
01 static sp<ISurfaceComposer> getComposerService() 02 { 03 sp<ISurfaceComposer> sc; 04 Mutex::Autolock _l(gLock); 05 if (gSurfaceManager != 0) { 06 sc = gSurfaceManager; 07 } else { 08 // release the lock while we're waiting... 09 gLock.unlock(); 10 11 sp<IBinder> binder; 12 sp<IServiceManager> sm = defaultServiceManager(); 13 do { 14 binder = sm->getService(String16("SurfaceFlinger")); 15 if (binder == 0) { 16 LOGW("SurfaceFlinger not published, waiting..."); 17 usleep(500000); // 0.5 s 18 } 19 } while(binder == 0); 20 21 // grab the lock again for updating gSurfaceManager 22 gLock.lock(); 23 if (gSurfaceManager == 0) { 24 sc = interface_cast<ISurfaceComposer>(binder); 25 gSurfaceManager = sc; 26 } else { 27 sc = gSurfaceManager; 28 } 29 } 30 return sc; 31 }sp<IServiceManager> defaultServiceManager()Android 圖形系統使用的是 client-server 的架構, client 與 server 位在不同的 process,彼此之間透過 binder 通信, 除了 client 與 server, Android 另外有一個全域的 service manager 用來管理各種 service. defaultServiceManager() 函式的功能就在獲得和 service manager 的通信管道, 程式代碼如下:
01 sp<IServiceManager> defaultServiceManager() 02 { 03 if (gDefaultServiceManager != NULL) return gDefaultServiceManager; 04 { 05 AutoMutex _l(gDefaultServiceManagerLock); 06 if (gDefaultServiceManager == NULL) { 07 gDefaultServiceManager = interface_cast<IServiceManager>( 08 ProcessState::self()->getContextObject(NULL)); 09 } 10 } 11 return gDefaultServiceManager; 12 }
看來每個 process, gDefaultServiceManager
只會有一份instance. 若是 gDefaultServiceManager 尚未建立, 則以下程式代碼會被執行:
gDefaultServiceManager =
interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
ProcessState::self() 函式程式代碼如下
\frameworks\base\libs\binder\ProcessState.cpp
01 sp<ProcessState> ProcessState::self() 02 { 03 if (gProcess != NULL) return gProcess; 04 05 AutoMutex _l(gProcessMutex); 06 if (gProcess == NULL) gProcess = new ProcessState; 07 return gProcess; 08 }
和 gDefaultServiceManager
一樣, 一個 process 中, gProcess 也只有一份instance, ProcessState 的建構式負責開啟 binder 驅動 (/dev/binder), 並且將 binder 的記憶體空間 mapping 到 virtual memory space.
讀者可以自行跟一下 ProcessState 的建構式代碼.
讀者可以自行跟一下 ProcessState 的建構式代碼.
回到
gDefaultServiceManager =
interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
其中 調用getContextObject(NULL); 得到和 services manager 之間的 binder(此處為 BpBinder), 這裡的interface_cast 蠻關鍵的, interface_cast
是一個 template,定義如下:
01 template<typename INTERFACE> 02 inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) 03 { 04 return INTERFACE::asInterface(obj); 05 }
由以上 interface_cast 的定義, 下面這一段程式碼
gDefaultServiceManager =
interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
等同於
gDefaultServiceManager = IServiceManager::asInterface(
const sp<IBinder>& obj);
現在關鍵來到IServiceManager::
asInterface(). 但是在 IServiceManager 這個 class 中找不到 asInterface () 函式的定義和宣告. IServiceManager 的父類別是 IInterface, 在IServiceManager.h 中引用了 IInterface.h , 在 IInterface.h找到了以下兩個巨集定義, 巨集定義中的符號 “##” 是”連接”的意思:
01 #define DECLARE_META_INTERFACE(INTERFACE) \ 02 static const String16 descriptor; \ 03 static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj); \ 04 virtual const String16& getInterfaceDescriptor() const; \ 05 I##INTERFACE(); \ 06 virtual ~I##INTERFACE(); \
01 #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ 02 const String16 I##INTERFACE::descriptor(NAME); \ 03 const String16& I##INTERFACE::getInterfaceDescriptor() const { \ 04 return I##INTERFACE::descriptor; \ 05 } \ 06 sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj) \ 07 { \ 08 sp<I##INTERFACE> intr; \ 09 if (obj != NULL) { \ 10 intr = static_cast<I##INTERFACE*>( \ 11 obj->queryLocalInterface( \ 12 I##INTERFACE::descriptor).get()); \ 13 if (intr == NULL) { \ 14 intr = new Bp##INTERFACE(obj); \ 15 } \ 16 } \ 17 return intr; \ 18 } \ 19 I##INTERFACE::I##INTERFACE() { } \ 20 I##INTERFACE::~I##INTERFACE() { } \
在 IServiceManager.h , 使用到的是DECLARE_META_INTERFACE巨集如下
01 DECLARE_META_INTERFACE(ServiceManager);
巨集展開後的程式代碼:
01 static const String16 descriptor; 02 static sp<IServiceManager > asInterface(const sp<IBinder>& obj); 03 virtual const String16& getInterfaceDescriptor() const; 04 IServiceManager (); 05 virtual ~ IServiceManager ();在 IServiceManager.cpp 則是使用到IMPLEMENT_META_INTERFACE巨集:
IMPLEMENT_META_INTERFACE(ServiceManager,
"android.os.IServiceManager");
巨集展開後程式代碼如下:
01 const String16 IServiceManager::descriptor("android.os.IServiceManager"); 02 const String16& IServiceManager::getInterfaceDescriptor() const { 03 return IServiceManager::descriptor; 04 } 05 sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder>& obj) { 06 sp<IServiceManager> intr; 07 if(obj!=NULL) { 08 intr=static_cast<IServiceManager*>( 09 obj->queryLocalInterface(IServiceManager::descriptor).get()); 10 if (intr == NULL) { 11 intr = new BpServiceManager(obj); 12 } 13 } 14 return intr; 15 } 16 IServiceManager::IServiceManager() { } 17 IServiceManager::~IServiceManager() { }
整個IServiceManager::asInterface()函式的關鍵是 new BpServiceManager(obj); 這一行程式代碼. 要注意, 這裡產生的是 BpServiceManager 類別的物件. 類別BpServiceManager繼承自 IServiceManager,
BpServiceManager建構式傳入的參數是
BpBinder 型態物件.提醒一下, 此 BpBinder 型態物件 是和 service manager 之間的 IPC. 在BpServiceManager物件中的mRemote 就是此BpBinder物件.
回到getComposerService() 函式, 取得 IServiceManager 介面(BpServiceManager物件)後,接下來要透過 BpServiceManager的getService()函式取得 SurfaceFlinger service 的資訊, 程式片段如下
01 binder = sm->getService(String16("SurfaceFlinger"));
關鍵在 getService() 這個函式, 看看程式碼:
/frameworks/base/libs/binder/IServiceManager.cpp
01 virtual sp<IBinder> getService(const String16& name) const 02 { 03 unsigned n; 04 for (n = 0; n < 5; n++){ 05 sp<IBinder> svc = checkService(name); 06 if (svc != NULL) return svc; 07 LOGI("Waiting for sevice %s...\n", String8(name).string()); 08 sleep(1); 09 } 10 return NULL; 11 }
調用checkService() 函式, 若返回為NULL, 則 process sleep 一秒鐘後繼續嘗試獲取, 最多嘗試五次. 這是為了防止 SurfaceFlinger
service 在嘗試獲取的當下還沒有啟動起來.
看看checkService()函式做了什麼:
/frameworks/base/libs/binder/IServiceManager.cpp
01 virtual sp<IBinder> checkService( const String16& name) const 02 { 03 Parcel data, reply; 04 data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); 05 data.writeString16(name); 06 remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); 07 return reply.readStrongBinder(); 08 }
宣告兩個Parcel 變數data, reply, 分別做為binder傳送和接收時的資料容器使用. 接下來
01 data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); 02 data.writeString16(name);
這兩行代碼等效於
01 data.writeInterfaceToken("android.os.IServiceManager"); 02 data.writeString16("SurfaceFlinger");
binder 通信是另一個精彩的主題, 這邊只要先理解成 client 透過 service manager 取得了和 surface flinger 之間的通信管道.
回到 static
sp<ISurfaceComposer> getComposerService() 函式中, 這段程式代碼
01 if (gSurfaceManager == 0) { 02 sc = interface_cast<ISurfaceComposer>(binder); 03 gSurfaceManager = sc; 04 } else { 05 sc = gSurfaceManager; 06 }
又是一個 interface_cast, 幸好前面已經介紹過了, 因此我們知道
這是產生一個
bpSurfaceComposer interface, 這個做法和 bpServiceManager 如出一轍.
bpSurfaceComposer 的程式代碼位於:
/frameworks/base/libs/surfaceflinger_client/ISurfaceComposer.cpp
現在, 我們回到 SurfaceComposerClient 的建構式:
01 SurfaceComposerClient::SurfaceComposerClient() 02 { 03 sp<ISurfaceComposer> sm(getComposerService()); 04 if (sm == 0) { 05 _init(0, 0); 06 return; 07 } 08 09 _init(sm, sm->createConnection()); 10 11 if (mClient != 0) { 12 Mutex::Autolock _l(gLock); 13 VERBOSE("Adding client %p to map", this); 14 gActiveConnections.add(mClient->asBinder(), this); 15 } 16 }
我們要看 _init(sm,
sm->createConnection()); 這一行代碼:
其中
sm->createConnection() 調用的是
bpSurfaceComposer 的
createConnection 函式如下:
01 virtual sp<ISurfaceFlingerClient> createConnection() 02 { 03 uint32_t n; 04 Parcel data, reply; 05 data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); 06 remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply); 07 return interface_cast<ISurfaceFlingerClient>(reply.readStrongBinder()); 08 }
透過bpSurfaceComposer
interface 的 binder 調用 surfaceflinger::createConnect() 函式, 要注意 interface_cast 在這裡又出現了, 我們可以預設 這裡會產生一個
bpSurfaceFlingerClient interface, 先來看 SurfaceFlinger::createConnection()函式:
01 sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection() 02 { 03 Mutex::Autolock _l(mStateLock); 04 uint32_t token = mTokens.acquire(); 05 06 sp<Client> client = new Client(token, this); 07 if (client->ctrlblk == 0) { 08 mTokens.release(token); 09 return 0; 10 } 11 status_t err = mClientsMap.add(token, client); 12 if (err < 0) { 13 mTokens.release(token); 14 return 0; 15 } 16 sp<BClient> bclient = 17 new BClient(this, token, client->getControlBlockMemory()); 18 return bclient; 19 }
比較關鍵的是 BClient 物件的建立, 它繼承自 BnSurfaceFlingerClient, 是用以回應客戶端 的請求.
結論
文章走了一遍 Android 2.2 建立 surface的相關代碼, 個人認為Android 的這個過程有精彩之處, 可以從中學習探討的東西不少, 例如文章中提到的 binder, service
manager 等, 都是可以另立文章深入介紹的主題. 歡迎有研究的同好提供心得.
沒有留言:
張貼留言