Android系統的Binder機制之三——服務代理對象(2)

文《Android系統的Binder機制之二——服務代理對象(1)》咱們學習了進程的C/C++層面的服務代理對象BpBinder,和Binder底層處理方式。本文咱們將深刻分析一下在進程的Java層面服務代理對象的建立和使用。html

Android進程的C/C++層面和Java層

    Android中程序大部分都是java開發,底層經過JNI調用C/C++的代碼。這樣一個程序就分爲了兩個層面C/C++層面和Java層面。運行狀態下,咱們說它們都在一個進程之中,擁有相同的進程屬性(UID,GID等等)。java

    Binder客戶程序的C/C++層面的對象和原理咱們在上文Android系統的Binder機制之二——服務代理對象(1)》已經學習。下面咱們將介紹客戶程序怎樣在Java層面經過JNI調用底層C/C++代碼的建立服務代理。android

ServiceManager類型和對象

    我在《Android系統的Binder機制之一——Service Manager》中介紹過,客戶端要想得到服務代理,首先要向ServiceManager查詢Service。在Java層面也是這樣,因此咱們首先分析Java層面ServiceManager類。cookie

    咱們經過查看ServiceManager的源碼咱們發現,ServiceManager類型也是一個Singleton類型。全部的方法都是靜態方法,全部靜態方法都是訪問它的IServiceManager類型的靜態變量sServiceManager,定義以下:網絡

 1: private static IServiceManager sServiceManager;

因此能夠理解ServiceManager就是IServiceManager對象的一個代理。爲建立和訪問這個變量都是經過ServiceManager的getIServiceManager方法,定義以下:app

 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方法,這裏就很少說了。this

    咱們能夠看出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代理對象的。這裏只是簡單說明一下調用順序,詳細過程請查看源碼。

一、調用ServiceManager.java中的ServiceManager靜態方法getService。

二、調用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對象。

三、查看Parcel.java中的readStrongBinder方法,發現是Native方法,將會調用到C/C++的代碼。

四、查看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對象。

五、查看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: }

六、查看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層。

七、Java層爲了用使用Service方便,能夠把Service代理對象——BpBinder對象(IBinder對象)封裝成一個對客戶程序友好的代理對象,就如前面ServiceManagerProxy所示那樣。

八、用戶程序就能夠經過該代理對象訪問相應Service了。

    經過所述,咱們瞭解了Service代理對象在Java層的建立和使用。Android系統的Binder機制博大精深,我在本文中不少方面都是走馬觀花,若是想深刻學習請參閱Android的源碼。

參考資料:

IPC框架分析 Binder,Service,Service manager

相關文章
相關標籤/搜索