2012年9月1日 星期六

Android 建立 surface 的過程


Android 的圖形系統是 Client-Server 架構, Server SurfaceFlinger, Client 則是應用程式.
應用程式第一次執行時, Window Management Service (WMS) 會開啟一個 session, openSession()函式會被調用. openSession()函式在BSP的位置和程式代碼如下:



\frameworks\base\services\java\com\android\server\WindowManagerService.java
Source3.cpp
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
Source3.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
Source3.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()函式, 程式代碼如下
Source3.cpp
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 的通信管道, 程式代碼如下:
Source3.cpp
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
Source3.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 的建構式代碼.
回到
gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));

其中 調用getContextObject(NULL); 得到和 services manager 之間的 binder(此處為 BpBinder), 這裡的interface_cast 蠻關鍵的, interface_cast 是一個 template,定義如下:
Source3.cpp
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找到了以下兩個巨集定義, 巨集定義中的符號 “##” 連接的意思:
Source3.cpp
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();         \
Source3.cpp
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巨集如下
Source3.cpp
01 DECLARE_META_INTERFACE(ServiceManager);

巨集展開後的程式代碼:    
Source3.cpp
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");
巨集展開後程式代碼如下:
Source3.cpp
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物件),接下來要透過 BpServiceManagergetService()函式取得 SurfaceFlinger service 的資訊, 程式片段如下
Source3.cpp
01 binder = sm->getService(String16("SurfaceFlinger"));

關鍵在 getService() 這個函式, 看看程式碼:
/frameworks/base/libs/binder/IServiceManager.cpp
Source3.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
Source3.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傳送和接收時的資料容器使用. 接下來
Source3.cpp
01 data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
02 data.writeString16(name);

這兩行代碼等效於
Source3.cpp
01 data.writeInterfaceToken("android.os.IServiceManager");
02 data.writeString16("SurfaceFlinger");

binder 通信是另一個精彩的主題, 這邊只要先理解成 client 透過 service manager 取得了和 surface flinger 之間的通信管道.

回到 static sp<ISurfaceComposer> getComposerService() 函式中, 這段程式代碼
Source3.cpp
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 的建構式:
Source3.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 }

我們要看 _init(sm, sm->createConnection()); 這一行代碼:
其中 sm->createConnection() 調用的是 bpSurfaceComposer createConnection 函式如下:
Source3.cpp
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()函式:
Source3.cpp
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 , 都是可以另立文章深入介紹的主題. 歡迎有研究的同好提供心得.

沒有留言:

張貼留言