上文《Android系統的Binder機制之二——服務代理對象(1)》我們學習了進程的C/C++層面的服務代理對象BpBinder,和Binder底層處理方式。本文我們將深入分析一下在進程的Java層面服務代理對象的建立和使用。
Android進程的C/C++層面和Java層
Android中程式大部分都是java開發,底層通過JNI調用C/C++的代碼。這樣一個程式就分為了兩個層面C/C++層面和Java層面。運行狀態下,我們說它們都在一個進程之中,擁有相同的進程屬性(UID,GID等等)。
Binder客戶程式的C/C++層面的對象和原理我們在上文《Android系統的Binder機制之二——服務代理對象(1)》已經學習。下面我們將介紹客戶程式怎樣在Java層面通過JNI調用底層C/C++代碼的建立服務代理。
ServiceManager類型和對象
我在《Android系統的Binder機制之一——Service Manager》中介紹過,用戶端要想獲得服務代理,首先要向ServiceManager查詢Service。在Java層面也是這樣,所以我們首先分析Java層面ServiceManager類。
我們通過查看ServiceManager的源碼我們發現,ServiceManager類型也是一個Singleton類型。所有的方法都是靜態方法,
所有靜態方法都是訪問它的IServiceManager類型的靜態變數sServiceManager,定義如下:
1: private static IServiceManager sServiceManager;
所以可以理解ServiceManager就是IServiceManager對象的一個代理。為建立和訪問這個變數都是通過ServiceManager的getIServiceManager方法,定義如下:
1: private static IServiceManager getIServiceManager() {
2: if (sServiceManager != null) {
3: return sServiceManager;
4: }
5:
6: // Find the service manager
7: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
8: return sServiceManager;
9: }
通過上面的代碼,非常清晰的告訴我們ServiceManager類型是一個Singleton類型。現在我們主要研究sServiceManager對象怎樣建立的。如下代碼建立IServiceManager對象:
1: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
我們首先查看BinderInternal類的getContextObject方法的代碼,發現是Native代
碼(哈哈!有終於到達C/C++層面了,我們已經熟悉了),對應的代碼為android_util_binder.cpp中的
android_os_BinderInternal_getContextObject函數,代碼如下:
1: static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
2: {
3: sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
4: return javaObjectForIBinder(env, b);
5: }
終於看到我們上文《Android系統的Binder機制之二——服務代理對象(1)》介紹過的ProcessState對象了,我們再去查看ProcessState對象的getContextObject方法,代碼如下:
1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
2: {
3: if (supportsProcesses()) {
4: return getStrongProxyForHandle(0);
5: } else {
6: return getContextObject(String16("default"), caller);
7: }
8: }
我們看到在當前進程的ProcessState對象其實是調用getStrongProxyForHandle方法來建立binder控制代碼為0的服務代理對象——BpBinder對象,我們在《Android系統的Binder機制之一——Service Manager》提到過ServiceManager的binder控制代碼是一個聞名控制代碼0。上文《Android系統的Binder機制之二——服務代理對象(1)》已經介紹過ProcessState對象的getStrongProxyForHandle方法,這裡就不多說了。
我們可以看出Java調用C/C++,建立一個服務代理對象BpBinder,在查看BpBinder的定義我們發現繼承自IBinder介面,然後在
android_util_binder.cpp中的方法android_os_BinderInternal_getContextObject中,把
C/C++層面的IBinder對象封裝成Java層面的IBinder對象。具體實現可以查看上文的
android_os_BinderInternal_getContextObject方法。
至此我們已經清楚BinderInternal.getContextObject(),返回的是ServiceManager的服務代理對象——
BpBinder對象。那麼ServiceManagerNative類的靜態方法asInterface做什麼用呢?我們還是通過代碼來分析,在
ServiceManagerNative.java中,asInterface的代碼如下:
1: static public IServiceManager asInterface(IBinder obj)
2: {
3: if (obj == null) {
4: return null;
5: }
6: IServiceManager in =
7: (IServiceManager)obj.queryLocalInterface(descriptor);
8: if (in != null) {
9: return in;
10: }
11:
12: return new ServiceManagerProxy(obj);
13: }
將會用IBinder對象建立一個ServiceManagerProxy對
象,ServiceManagerProxy類型繼承了IServiceManager介面,所以asInterface方法最終目的是用一個
IBinder對象建立一個IServiceManager對象。
為什麼要用IBinder對象建立一個IServiceManager對象呢?通過ServiceManager的代理對象——IBinder對象(BpBinder對象)應該可以直接請求ServiceManager中的服務了啊?我們在前文《Android系統的Binder機制之二——服務代理對象(1)》簡單介紹了一下IBinder類型,用戶端通過transact方法向Service發送請求,用戶端的onTransact被調用處理用戶端的請求,請求通過請求代碼來區分。具體請參考Android手冊。
如果用戶端直接用調用ServiceManager的代理對象的IBinder介面,那麼用戶端必須要記住所有請求的請求代碼,對用戶端來說不太友好。所
以在ServiceManagerNative類中就把ServiceManager的代理對象——IBinder對象(BpBinder對象)封裝成
ServiceManagerProxy對象,暴露給客戶程式一個IServiceManager介面,這樣IServiceManager對象將會代理
客戶程式發往ServiceManager的代理對象的請求。並且是調用IServiceManager對象的方法來給ServiceManager發送
請求,這樣對客戶程式來講和本地的函數調用是一致的,介面非常友好。比如我們客戶程式需要調用IServiceManager的getService方法
來查詢一個Service,ServiceManagerProxy實現代碼如下:
1: public IBinder getService(String name) throws RemoteException {
2: Parcel data = Parcel.obtain();
3: Parcel reply = Parcel.obtain();
4: data.writeInterfaceToken(IServiceManager.descriptor);
5: data.writeString(name);
6: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
7: IBinder binder = reply.readStrongBinder();
8: reply.recycle();
9: data.recycle();
10: return binder;
11: }
我們可以非常清晰的看到ServiceManagerProxy對象將客戶程式的請求轉換成對ServiceManager代理對象——IBinder對
象(BpBinder對象)的調用。後文我們將會詳細介紹怎樣通過IServiceManager查詢和獲得一個系統Service代理對象。
到這裡我們已經分析完了,ServiceManager的Singleton對象——sServiceManager的建立。如果有不清楚的地方請查看代碼。
查詢和獲得Service代理對象
客戶程式通過調用ServiceManager類型的靜態方法asInterface獲得了IServiceManager對象,但是最終目的一般都是要查詢和獲得其他的Service,一般都是要調用IServiceManager的getService方法,向ServiceManager獲得其他的Service。比如:
1: IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
上面的代碼中就是調用ServiceManager的靜態方法獲得網路管理服務代理對象。我們順藤摸瓜,看看系統是怎樣產生這個Service代理對象的。這裡只是簡單說明一下調用順序,詳細過程請查看源碼。
1、調用ServiceManager.java中的ServiceManager靜態方法getService。
2、調用ServiceManagerNative.java中的ServiceManagerProxy方法getService。代碼如下:
1: public IBinder getService(String name) throws RemoteException {
2: Parcel data = Parcel.obtain();
3: Parcel reply = Parcel.obtain();
4: data.writeInterfaceToken(IServiceManager.descriptor);
5: data.writeString(name);
6: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
7: IBinder binder = reply.readStrongBinder();
8: reply.recycle();
9: data.recycle();
10: return binder;
11: }
請注意IBinder的transact方法是同步方法(本例中ServiceManager處理完成請求之後才會返回),我們可以看出調用transact之後,調用reply.readStrongBinder()來讀取IBinder對象。
3、查看Parcel.java中的readStrongBinder方法,發現是Native方法,將會調用到C/C++的代碼。
4、查看android_util_binder.cpp中的android_os_Parcel_readStrongBinder函數。代碼如下:
1: static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
2: {
3: Parcel* parcel = parcelForJavaObject(env, clazz);
4: if (parcel != NULL) {
5: return javaObjectForIBinder(env, parcel->readStrongBinder());
6: }
7: return NULL;
8: }
parcel->readStrongBinder()將會產生一個IBinder對象。
5、查看Parcel.cpp中,Parcel的方法readStrongBinder。代碼如下:
1: sp<IBinder> Parcel::readStrongBinder() const
2: {
3: sp<IBinder> val;
4: unflatten_binder(ProcessState::self(), *this, &val);
5: return val;
6: }
6、查看Parcel.cpp中,Parcel的方法unflatten_binder。代碼如下:
1: status_t unflatten_binder(const sp<ProcessState>& proc,
2: const Parcel& in, sp<IBinder>* out)
3: {
4: const flat_binder_object* flat = in.readObject(false);
5:
6: if (flat) {
7: switch (flat->type) {
8: case BINDER_TYPE_BINDER:
9: *out = static_cast<IBinder*>(flat->cookie);
10: return finish_unflatten_binder(NULL, *flat, in);
11: case BINDER_TYPE_HANDLE:
12: *out = proc->getStrongProxyForHandle(flat->handle);
13: return finish_unflatten_binder(
14: static_cast<BpBinder*>(out->get()), *flat, in);
15: }
16: }
17: return BAD_TYPE;
18: }
終於看到調用我們的老朋友ProcessState對象的getStrongProxyForHandle方法了,這樣將會建立一個BpBinder對象,然後該BpBinder對象將會被轉換成IBinder對象返回給Java層。
7、Java層為了用使用Service方便,可以把Service代理對象——BpBinder對象(IBinder對象)封裝成一個對客戶程式友好的代理對象,就如前面ServiceManagerProxy所示那樣。
8、使用者程式就可以通過該代理對象訪問相應Service了。
通過所述,我們瞭解了Service代理對象在Java層的建立和使用。Android系統的Binder機制博大精深,我在本文中很多方面都是蜻蜓點水,如果想深入學習請參閱Android的源碼。
參考資料:
IPC架構分析 Binder,Service,Service manager
原文