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

來源:互聯網
上載者:User

上文《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

原文


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.