Binder in Java

來源:互聯網
上載者:User

  Android在Native層實現了進程間的Binder通訊,但是上層應用程式的開發及Framework的實現都是Java,用Java層再實現一次肯定是不合理的,Java可以通過JNI調用Native Code,所以通過JNI複用Binder在Native層的實現就是一個順理成章的事情。

註冊Service

  在Init進程的init2階段,系統啟動了ServerThread,在ServerThread中會啟動很多用Java實現的系統服務,比如說PowerService:

power = 

  建立Server端實體,然後向ServiceManager註冊,從代碼錶面看是和Native層Binder一樣的。PowerManagerService繼承自Java層的Binder類:

   PowerManagerService   IPowerManager     Stub  android.os.Binder  android.os.IPowerManager {

  在以在new PowerManagerService時會調用Binder的建構函式,Binder的建構函式中調用了init(),init是native方法,執行JNI的android_os_Binder_init:

  android_os_Binder_init(JNIEnv** jbh =  (jbh =="java/lang/OutOfMemoryError""Java Binder %p: acquiring first ref on holder %p"->incStrong((*->SetIntField(obj, gBinderOffsets.mObject, (

  在android_os_Binder_init,建立了一個JavaBBinderHolder對角,並將其指標儲存在了obj即Binder的gBinderOffsets.mObject域中,而gBinderOffsets.mObject又是個什麼東西?看一下它的定義:

 

  在AndroidRuntine::startReg中會調用register_android_os_Binder,register_android_os_Binder會調用int_register_android_os_Binder等函數建立Java層Binder、BinderProxy、BinderInternal、Log等與Native層的映射關係。比如在int_register_android_os_Binder中會通過JNI標準的方法GetMethodID等初始化gBinderOffsets:

  int_register_android_os_Binder(JNIEnv*= env->== NULL, = (jclass) env->= env->GetMethodID(clazz, , = env->GetFieldID(clazz, , 

  在android_os_Binder_init中new了一個JavaBBinderHolder,JavaBBinderHolder new了一個JavaBBinder儲存到了自己的成員wp<JavaBBinder> mBinder中。

  JavaBBinder繼承自Native層的BBinder,並且將Java層的Binder對象(此處即PowerManagerService)儲存到了成員mObject中,並通過object()方法返回。

  現在我們發現,JavaBinder,BinderBBinderHolder,JavaBBinder存在相互參考關聯性:

    PowerManagerService.mObject->JavaBBinderHolder
    JavaBBinderHolder.mBinder->JavaBBinder
    JavaBBinder.mObject->PowerManagerService

  Binder是一種Client-Server類型的IPC,PowerManagerService屬於Server端,從Native Binder中我們知道,Client通過BpBinder經由Binder Driver、BBinder與Serverr通訊,PowerManagerService通過JavaBBinderHolder引用JavaBBinder,而JavaBBinder繼承自BBinder,符合了Server的條件,Server實體有了,接下來就要向ServiceManager註冊,通過以下方法:

    (sServiceManager != 

   BinderInternal.getContextObject是一個Native方法,調用JNIandroid_os_BinderInternal_getContextObject:

 jobject android_os_BinderInternal_getContextObject(JNIEnv*<IBinder> b = ProcessState::self()->

  ProcessState::self()->getContextObject就很熟悉了,在Binder in Native中可以知道,這個調用返回new BpBinder(0)。

  javaObjectForIBinder的作用就是,建立一個Java層的BinderProxy對象,將Native層的BpBinder儲存到BinderProxy.mObject,並將BinderProxy的弱引用通過attachObject儲存到Native層的BpBinder(成員mObjects中),這樣Java層的BinderProxy與Native層的BpBinder就可以相互引用了。Java層的BinderProxy及其在Native層的表示間的映射關係同Binder類一樣也是在register_android_os_Binder中建立的。

  上面紅色的部分就等效於:

gServiceManager = ServiceManagerNative.asInterface( BinderProxy());

   ServiceManagerNative繼承自IServiceManager與Java層的Binder類,BinderProxy可以引用BpBinder。asInterface就像Native Binder中的interface_cast的,asInterface實現可以簡化為:

  ServiceManagerProxy(obj);

  obj是BinderProxy對象。ServiceManagerProxy直接將這個BinderProxy對象儲存在了成員mRemote中,並通過asBinder返回。

  ServiceManagerProxy同時實現了IServiceManager,而且由其名字可知,ServiceManagerProxy是作為ServiceManager在Client端的代理的,看下它的addService的實現:

  addService(String name, IBinder service, ==        data.writeInt(allowIsolated ? 1 : 0        reply.recycle();        data.recycle();    }

  writeStrongBinder是Native方法,調用android_os_Parcel_writeStrongBinder,在android_os_Parcel_writeStrongBinder將Java Parcel轉換成Native Parcel(Native Parcel的指標儲存在Java Parcel的成員變數中),然後調用以下語句:

 status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, ));

  sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)根據obj返回JavaBBinder或Native BpBinder,在這裡傳入的obj 是PowerManagerService,返回JavaBBinder。接下來調用了mRemote.transact,mRemote是BinderProxy的對象。

  BinderProxy的transact是Native方法,調用JNIandroid_os_BinderProxy_transact,在android_os_BinderProxy_transact中通過:

IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject);
...
status_t err = target->transact(code, *data, reply, flags);

  擷取到BinderProxy中儲存的BpBinder,然後調用BpBinder的transact,到這裡就和Native Binder的調用流程一樣了,Native ServiceManager會註冊我們的Service,在這裡是PowerManagerService。

 獲得註冊的Service

  Service已經向ServiceManager註冊了,那麼我們怎麼獲得所註冊的Service,或者更準確地說,怎麼獲得所註冊的Service的代理呢?

  回想下我們在APK中是怎麼擷取系統服務的:

PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

  看一下getSystemService的實現,位於ContextImpl中:

= fetcher ==  ?  : fetcher.getService(                }});

  1. ServiceManager.getService獲得IBinder對象

  同ServiceManager.addService一樣,ServiceManager.getService首先獲得一個ServiceManagerProxy的對象,然後調用它的getService方法:

     IBinder getService(String name) 0=

  mRemote是BinderProxy對象,內部引用了BpBinder,調用BinderProxy的Native方法transact與Binder通訊,然後通過readStrongBinder()讀取返回的資料,一個IBinder對象。

  readStrongBinder中通過javaObjectForIBinder返回了BinderProxy對象,前面已經說過。

  2. 通過asInterface將獲得的IBinder對象轉換成IPowerManager對象

  IPowerManager.Stub.asInterface可以簡化為:

  android.os.IPowerManager.Stub.Proxy(obj);

  Proxy只是將傳入的參數(BinderProxy)儲存到了成員mRemote中並通過asBinder返回。

  Proxy與Stub都是IPowerManager.aidl編譯後產生的類,都位於IPowerManager.java中。關於aidl網上有很多資料。

  3. IPowerManager對象是不向外暴露的,構造一個PowerManager封裝IPowerManager返回。

  PowerManager只是將IPowerManager儲存在了成員變數中,PowerManager中儲存了BinderProxy,BinderProxy中引用了Native BpBinder,就可以與Server進行通訊了。

Server端響應Client請求

  Server端接收到Client的請求後會調用BBinder的transact處理請求,transact會調用虛函數onTransact,JavaBBinder繼承自BBinder,所以會調用JavaBBinder::onTransact,在JavaBBinder::onTransact中有以下一句:

jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, (int32_t)&data, (int32_t)reply, flags);

  通過JNI反向調用了Java類的方法。前面我們知道了,Java實現的Service中,Service對象,JavaBBinderHolder,JavaBBinder存在相互參考關聯性,JavaBBinder的成員mObject引用了Java中的Service對象,比如此處的PowerManagerService,而且在int_register_android_os_Binder中通過

gBinderOffsets.mExecTransact  = env->GetMethodID(clazz, , );

  將Service的execTransact方法(其實是Binder的方法)儲存在了gBinderOffsets.mExecTransact中,所在以JavaBBinder::onTransact中會調用Binder.execTransact。在Binder.execTransact中調用了onTransact,執行子類即Stub類的onTransact方法,在onTransact中根據code值執行相應的方法,最終是調用Service類(繼承自Stub)中相應的方法。

總結

  Java層通過JNI利用了Native層的Binder,在JNI函數註冊時會建立Java層Binder,BinderProxy,BinderProxy等類與Native層的映射關係。Java層Service實體繼承自Java層的Binder類,在Binder類初始化時會建立一個JavaBBinderHolder作為JavaBBinder的容器,JavaBBinder繼承自BBinder,Java層Binder類引用JavaBBinderHolder,JavaBBinderHolder引用JavaBBinder,JavaBBinder繼承自BBinder並引用Java層的Binder類,這三者互相引用,這樣Java層的Service實體就可以通過BBinder與驅動進行通訊了。

  進程向Java層的ServiceManager代理髮送GET_SERVICE請求,然後通過JNI向Native層的ServiceManager請求服務,Native層的ServiceManager返回請求的服務的代理對你BpBinder,通過javaObjectForIBinder函數將Native的BbBinder轉化為Java層對應的BinderProxy,然後通過aidl產生的Stub類asInterface方法將BinderProxy封閉到請求的服務的代理對象中,這個代理對象引用了BinderProxy,BinderProxy內部儲存了Native層的BpBinder,這樣就可以與驅動進行通訊了。

  當Server端接收到Client的請求時會通過BBinder的transact調用Server的服務,BBinder的transact調用虛函數onTransact,這樣就會調到BBinder的子類JavaBBinder的onTransact,而JavaBinder::onTransact會通過JNI反向調用到Java層Binder類的execTransact,Binder.execTransact調用onTransact即子類Stub的onTransact,然後根據code值調用Service實體類(繼承自Stub)相應的方法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.