日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Binder源码分析之Java层(原)

發布時間:2025/3/15 java 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Binder源码分析之Java层(原) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?? ? ? 前面的幾節中我們介紹了Native層Binder通訊的原理和用法,那么在Java層如何使用Binder通訊呢?其原理又與Native層的Binder有什么關系呢?
? ? ? ? 與Native層的ServiceManager類似,Android在Java層也有一個ServiceManager用于處理Java層Service的注冊、申請。只不過, Java層的這個ServiceManager,其實是在Java層建立的ServiceManager的代理,他把Java層客戶端的各項請求傳遞到Native層的ServiceManager進行處理
? ? ? ? 而對于其他Java層的Service來說,客戶端得到的Service遠程代理對象,就是Native層得到的BpXXXService對象。
? ? ? ? 接下來我們分四部分來介紹Java層Binder機制:
? ? ? ?? 1、ServiceManager的結構
? ? ? ?? 2、如何注冊一個Service
? ? ? ?? 3、如何得到一個Service

? ? ? ??4、Service代理對象方法的過程


一、ServiceManager的結構

? ? ? ? 我們來看一下ServiceManager類的代碼: [java]?view plaincopy
  • @ServiceManager.java(google-code\frameworks\base\core\java\android\os\ServiceManager.java)??
  • public?final?class?ServiceManager?{??
  • ????private?static?IServiceManager?getIServiceManager()?{??
  • ????}??
  • ????public?static?IBinder?getService(String?name)?{??
  • ????}??
  • ????public?static?void?addService(String?name,?IBinder?service)?{??
  • ????}??
  • ????public?static?void?addService(String?name,?IBinder?service,?boolean?allowIsolated)?{??
  • ????}??
  • ????public?static?IBinder?checkService(String?name)?{??
  • ????}??
  • ????public?static?String[]?listServices()?throws?RemoteException?{??
  • ????}??
  • ????public?static?void?initServiceCache(Map<String,?IBinder>?cache)?{??
  • ????}??
  • }??
  • ? ? ? ? 這個類比較簡單,而且我們看到,ServiceManager沒有繼承任何的類,那么他是如何實現“管理員”的角色呢?


    二、如何在Java層通過ServiceManager注冊一個Service

    ? ? ? ? Android啟動時,將會在SystemServer中的ServerThread線程中將一些重要的Java層Service注冊并啟動,我們在這里挑選負責狀態欄管理的StatusBarManagerService來分析。 [java]?view plaincopy
  • @SystemServer.java(google-code\frameworks\base\services\java\com\android\server\SystemServer.java)??
  • class?ServerThread?extends?Thread?{??
  • ????@Override??
  • ????public?void?run()?{??
  • ????????try?{??
  • ????????????statusBar?=?new?StatusBarManagerService(context,?wm);??
  • ????????????//調用ServiceManager注冊服務??
  • ????????????ServiceManager.addService(Context.STATUS_BAR_SERVICE,?statusBar);??
  • ????????}?catch?(Throwable?e)?{??
  • ????????????reportWtf("starting?StatusBarManagerService",?e);??
  • ????????}??
  • ????}??
  • }??
  • ? ? ? ? 我們看到,作為一個Service,可以通過調用ServiceManager的addService()方法注冊自己。注冊的時候傳遞了兩個參數,Context.STATUS_BAR_SERVICE作為該Service的name,StatusBarManagerService作為該Service的BBinder子類對象,一起傳遞給了ServiceManager。這樣的形式正符合Native層ServiceManager中Service的注冊方式。
    ? ? ? ? 我們來看ServiceManager的addService()方法: [java]?view plaincopy
  • @ServiceManager.java??
  • public?static?void?addService(String?name,?IBinder?service)?{??
  • ????try?{??
  • ????????getIServiceManager().addService(name,?service,?false);??
  • ????}?catch?(RemoteException?e)?{??
  • ????????Log.e(TAG,?"error?in?addService",?e);??
  • ????}??
  • }??
  • ? ? ? ? 在addService()內部,把addService()的請求轉發給了getIServiceManager()得到的對象。 [java]?view plaincopy
  • private?static?IServiceManager?sServiceManager;??
  • private?static?IServiceManager?getIServiceManager()?{??
  • ????if?(sServiceManager?!=?null)?{??
  • ????????//單例模式??
  • ????????return?sServiceManager;??
  • ????}??
  • ????//得到ServiceManager的Java層代理對象??
  • ????sServiceManager?=?ServiceManagerNative.asInterface(BinderInternal.getContextObject());??
  • ????return?sServiceManager;??
  • }??
  • ? ? ? ? 這里看到,通過getIServiceManager()可以得到一個IServiceManager類型的sServiceManager對象, 那么這個對象究竟是什么屬性的呢
    ? ? ? ? 其實 我們通過getIServiceManager()得到的就是Java層中的ServiceManager的代理對象ServiceManagerProxy 。為了得到這個對象,我們需要經過兩步的準備:
    ? ? ? ?? 1、通過Native層的調用得到ServiceManager的遠程對象BpBinder
    ? ? ? ? ? ? ----也就是BinderInternal.getContextObject()的操作
    ? ? ? ? ?2、把ServiceManager的BpBinder封裝為Java層可用的ServiceManagerProxy對象
    ? ? ? ? ? ? ----也就是ServiceManagerNative().asInterface()的操作
    ? ? ? ? 下面我們來詳細分析這兩個步驟

    2.1、得到ServiceManager的BpBinder對象過程

    ? ? ? ? 這一步中我們將會看到, 如何通過BinderInternal.getContextObject()得到ServiceManager的BpBinder()對象 ,下面我們來看這個方法的聲明: [java]?view plaincopy
  • @BinderInternal.java(google-code\frameworks\base\core\java\com\android\internal\os\BinderInternal.java)??
  • public?static?final?native?IBinder?getContextObject();??
  • ? ? ? ? 他的聲明方式說明這個方法是在Native中被實現的,那么他具體定義是在哪里呢?
    ? ? ? ? 我們簡單來說一下流程。
    ? ? ? ? 在Java虛擬機啟動時,將會注冊一系列的native方法 [java]?view plaincopy
  • @AndroidRuntime.cpp(google-code\frameworks\base\core\jni\AndroidRuntime.cpp)??
  • void?AndroidRuntime::start(const?char*?className,?const?char*?options)?{??
  • ????//開始注冊方法??
  • ????if?(startReg(env)?<?0)?{??
  • ????????return;??
  • ????}??
  • }??
  • ? ? ? ? 在虛擬機啟動時,將會通過startReg()方法去注冊jni: [java]?view plaincopy
  • int?AndroidRuntime::startReg(JNIEnv*?env)?{??
  • ????//注冊gRegJNI列表中的jni方法??
  • ????if?(register_jni_procs(gRegJNI,?NELEM(gRegJNI),?env)?<?0)?{??
  • ????????env->PopLocalFrame(NULL);??
  • ????????return?-1;??
  • ????}??
  • ????return?0;??
  • }??
  • ? ? ? ? 在上面的startReg()中將會遍歷gRegJNI列表并注冊,我們來看需要注冊的列表內容: [java]?view plaincopy
  • static?const?RegJNIRec?gRegJNI[]?=?{??
  • ????REG_JNI(register_android_os_Binder),??
  • };??
  • ? ? ? ? 其中就包括了register_android_os_Binder(): [java]?view plaincopy
  • @android_util_Binder.cpp(google-code\frameworks\base\core\jni\android_util_Binder.cpp)??
  • int?register_android_os_Binder(JNIEnv*?env)?{??
  • ????//注冊BinderInternal中的jni??
  • ????if?(int_register_android_os_BinderInternal(env)?<?0)??
  • ????????return?-1;??
  • ????return?0;??
  • }??
  • ? ? ? ? 在register_android_os_Binder中對BinderInternal中的jni進行注冊: [java]?view plaincopy
  • static?int?int_register_android_os_BinderInternal(JNIEnv*?env)?{??
  • ????jclass?clazz;??
  • ????//根據路徑找到類??
  • ????clazz?=?env->FindClass(kBinderInternalPathName);??
  • ????gBinderInternalOffsets.mClass?=?(jclass)?env->NewGlobalRef(clazz);??
  • ????gBinderInternalOffsets.mForceGc?=?env->GetStaticMethodID(clazz,?"forceBinderGc",?"()V");??
  • ??
  • ????//注冊gBinderInternalMethods中的jni??
  • ????return?AndroidRuntime::registerNativeMethods(??
  • ????????????env,?kBinderInternalPathName,??
  • ????????????gBinderInternalMethods,?NELEM(gBinderInternalMethods));??
  • }??
  • ? ? ? ? 我們再來看gBinderInternalMethods中定義的方法: [java]?view plaincopy
  • static?const?JNINativeMethod?gBinderInternalMethods[]?=?{??
  • ????{?"getContextObject",?"()Landroid/os/IBinder;",?(void*)android_os_BinderInternal_getContextObject?},??
  • ????{?"joinThreadPool",?"()V",?(void*)android_os_BinderInternal_joinThreadPool?},??
  • ????{?"disableBackgroundScheduling",?"(Z)V",?(void*)android_os_BinderInternal_disableBackgroundScheduling?},??
  • ????{?"handleGc",?"()V",?(void*)android_os_BinderInternal_handleGc?}??
  • };??
  • ? ? ? ? 這個數組中就定義了getContextObject方法所對應的jni實現,其實就是android_os_BinderInternal_getContextObject(),也就是說,getContextObject()將會調用到android_os_BinderInternal_getContextObject(),我們看一下這個方法的定義: [java]?view plaincopy
  • static?jobject?android_os_BinderInternal_getContextObject(JNIEnv*?env,?jobject?clazz)?{??
  • ????//得到BpBinder(0)對象??
  • ????sp<IBinder>?b?=?ProcessState::self()->getContextObject(NULL);??
  • ????//將BpBinder對象轉換為Java對象??
  • ????return?javaObjectForIBinder(env,?b);??
  • }??
  • ? ? ? ? 在這個方法中,完成了兩步重要的操作:
    ? ? ? ?? 1、通過ProcessState的getContextObject(NULL)得到了ServiceManager的BpBinder(0)對象 (詳細過程在《Binder源碼分析之Native層》中做過詳細介紹)。
    ? ? ? ?? 2、通過javaObjectForIBinder()方法把得到的BpBinder對象封裝成Java層可用的類型
    ? ? ? ? 至此,我們就拿到了Java層可用的ServiceManager的BpBinder對象, 下面要做的就是把該對象轉換為Java層可用的ServiceManager代理對象

    2.2、用BpBinder得到ServiceManagerProxy對象過程

    ? ? ? ? 我們在第二節剛開始的地方介紹過,Service注冊自己的時候需要在ServiceManager中通過getIServiceManager()方法得到ServiceManager在Java層的代理對象,然后調用該對象的addService()方法完成注冊: [java]?view plaincopy
  • private?static?IServiceManager?getIServiceManager()?{??
  • ????if?(sServiceManager?!=?null)?{??
  • ????????//單例模式??
  • ????????return?sServiceManager;??
  • ????}??
  • ????//得到ServiceManager的Java層代理對象??
  • ????sServiceManager?=?ServiceManagerNative.asInterface(BinderInternal.getContextObject());??
  • ????return?sServiceManager;??
  • }??
  • ? ? ? ? 經過前面2.1的分析,我們了解了通過BinderInternal.getContextObject()可以得到BpBinder(0)的Java層代理對象,接下來就需要 調用ServiceManagerNative的asInterface()方法將該對象轉換為Java層可用的ServiceManager代理對象
    ? ? ? ? 也就是說,當前的getIServiceManager()相當于: [java]?view plaincopy
  • private?static?IServiceManager?getIServiceManager()?{??
  • ????//得到ServiceManager的Java層代理對象??
  • ????sServiceManager?=?ServiceManagerNative.asInterface(BpBinder(0));??
  • ????return?sServiceManager;??
  • }??
  • ? ? ? ? 我們接下來看ServiceManagerNative的asInterface()的過程。 [java]?view plaincopy
  • @ServiceManagerNative.java(google-code\frameworks\base\core\java\android\os\ServiceManagerNative.java)??
  • static?public?IServiceManager?asInterface(IBinder?obj)??
  • {??
  • ????if?(obj?==?null)?{??
  • ????????return?null;??
  • ????}??
  • ????//查詢本地緩存??
  • ????IServiceManager?in?=?(IServiceManager)obj.queryLocalInterface(descriptor);??
  • ????if?(in?!=?null)?{??
  • ????????return?in;??
  • ????}??
  • ????//創建代理對象??
  • ????return?new?ServiceManagerProxy(obj);??
  • }??
  • ? ? ? ? 我們看到,通過asInterface()的轉換, 我們用BpBinder對象生成了ServiceManagerProxy對象
    ? ? ? ? 也就是說, 通過getIServiceManager()得到的sServiceManager對象,其實是ServiceManagerProxy對象

    2.3、ServiceManagerProxy對象

    ? ? ? ? 我們先來看一下其繼承結構: [java]?view plaincopy
  • class?ServiceManagerProxy?implements?IServiceManager?{}??
  • ? ? ? ? 從繼承關系上來看, ServiceManagerProxy實現了IServiceManager中定義的接口
    ? ? ? ? 然后再來看其構造函數,在2.2中介紹過,創建ServiceManagerProxy對象時,是用ServiceManager的BpBinder對象作為參數的: [java]?view plaincopy
  • public?ServiceManagerProxy(IBinder?remote)?{??
  • ????mRemote?=?remote;??
  • }??
  • ? ? ? ? 這里的構造函數中,把BpBinder(0)保存在了mRemote變量中。
    ? ? ? ? 下面我們來看ServiceManagerProxy中的方法: [java]?view plaincopy
  • class?ServiceManagerProxy?implements?IServiceManager?{??
  • ????public?ServiceManagerProxy(IBinder?remote)?{??
  • ????}??
  • ??
  • ????public?IBinder?asBinder()?{??
  • ????}??
  • ??
  • ????public?IBinder?getService(String?name)?throws?RemoteException?{??
  • ????}??
  • ??
  • ????public?IBinder?checkService(String?name)?throws?RemoteException?{??
  • ????}??
  • ??
  • ????public?void?addService(String?name,?IBinder?service,?boolean?allowIsolated)?throws?RemoteException?{??
  • ????}??
  • ??
  • ????public?String[]?listServices()?throws?RemoteException?{??
  • ????}??
  • ??
  • ????public?void?setPermissionController(IPermissionController?controller)?throws?RemoteException?{??
  • ????}??
  • }??
  • ? ? ? ? 我們看到,ServiceManagerProxy確實實現了IServiceManager中的方法,提供了add、get、check、list等功能。

    2.4、注冊Service的過程

    ? ? ? ? 經過以上的分析,我們知道通過getIServiceManager()的調用,我們得到的是ServiceManagerProxy對象,那么當注冊Service時調用的addService()方法就會調用到ServiceManagerProxy中: [java]?view plaincopy
  • public?void?addService(String?name,?IBinder?service,?boolean?allowIsolated)?throws?RemoteException?{??
  • ????Parcel?data?=?Parcel.obtain();??
  • ????Parcel?reply?=?Parcel.obtain();??
  • ????data.writeInterfaceToken(IServiceManager.descriptor);??
  • ????data.writeString(name);??
  • ????data.writeStrongBinder(service);??
  • ????data.writeInt(allowIsolated???1?:?0);??
  • ????mRemote.transact(ADD_SERVICE_TRANSACTION,?data,?reply,?0);??
  • ????reply.recycle();??
  • ????data.recycle();??
  • }??
  • ? ? ? ? 在addService的時候,將當前Service的name和service對象封裝到Parcel類型的data中,然后調用mRemote對象的transact()方法發送出去,并標記當前的操作是“ADD_SERVICE_TRANSACTION”,還記得我們在分析ServiceManagerProxy的構造函數時傳遞的參數其實是BpBinder對象,那么這里的transact()就會調用到BpBinder中: [java]?view plaincopy
  • @BpBinder.cpp??
  • status_t?BpBinder::transact(?uint32_t?code,?const?Parcel&?data,?Parcel*?reply,?uint32_t?flags)?{??
  • ????if?(mAlive)?{??
  • ????????//進入IPCThreadState繼續調用??
  • ????????status_t?status?=?IPCThreadState::self()->transact(?mHandle,?code,?data,?reply,?flags);??
  • ????????if?(status?==?DEAD_OBJECT)?mAlive?=?0;??
  • ????????return?status;??
  • ????}??
  • ????return?DEAD_OBJECT;??
  • }??
  • ? ? ? ? 到這里,就進入了Native層Binder的使用了,接下來就是經過IPCThreadState把請求發送到Binder驅動,然后在ServiceManager的進程中檢測到請求并處理,這個過程在Native層分析時詳細介紹過,這里就不再分析了。
    ? ? ? ? 經過以上的分析,我們對Java層ServiceManager有了全新的認識, 簡單來說,Java層的ServiceManager就是Native層ServiceManager的一個Client,而對于Java層其他Service來說,Java層的ServiceManager又是一個Service,負責把其他Client的請求轉發給Native層的ServiceManager去處理
    ? ? ? ? 而ServiceManagerProxy又是Java層ServiceManager的代理,其負責將Java層其他客戶端對ServiceManager的調用傳遞給Native層的ServiceManager。

    ? ? ? ? 下面用一張圖來示意Java層ServiceManager和Native層ServiceManager的關系:

    ? ??

    三、客戶端如何得到一個Service

    ? ? ? ? 前面分析了如何在Java層注冊一個Service,下面我們來分析,如何在Java層得到某個Service服務。
    ? ? ? ? 這一次我們挑選simphonebook這個Service來分析,先簡單來看一下其注冊成為Service的過程: [java]?view plaincopy
  • @IccPhoneBookInterfaceManagerProxy.java(google-code\frameworks\opt\telephony\src\java\com\android\Internal\telephony\)??
  • public?IccPhoneBookInterfaceManagerProxy(IccPhoneBookInterfaceManager?iccPhoneBookInterfaceManager)?{??
  • ????mIccPhoneBookInterfaceManager?=?iccPhoneBookInterfaceManager;??
  • ????if(ServiceManager.getService("simphonebook")?==?null)?{??
  • ????????ServiceManager.addService("simphonebook",?this);??
  • ????}??
  • }??
  • ? ? ? ? 這就是simphonebook的注冊過程,看似簡單,但是有個疑問,我們知道,在addService()的操作時,必須傳遞2個參數:name+IBinder子類對象,但是這里的this所指的IccPhoneBookInterfaceManagerProxy對象,是IBinder子類的對象嗎?
    ? ? ? ? 我們來看IccPhoneBookInterfaceManagerProxy這個類的繼承關系: [java]?view plaincopy
  • public?class?IccPhoneBookInterfaceManagerProxy?extends?IIccPhoneBook.Stub?{}??
  • ? ? ? ? 我們看到,他繼承了一個IIccPhoneBook.Stub的父類,這個父類是什么屬性呢?他和BBinder的子類嗎?
    ? ? ? ? 我們在代碼中找不到IIccPhoneBook.Stub的文件或類,但是找到了IIccPhoneBook.aidl文件,這個文件的作用又是什么呢?
    ? ? ? ? 原來,這里的 AIDL文件是Android中定義的接口語言(Android Interface Definition Language)。開發者只要按照指定的格式創建AIDL文件,系統就會自動為該文件生成一個對應的Java文件
    ? ? ? ? 假如我們創建一個IMyService.aidl文件,其內容為: [java]?view plaincopy
  • @IMyService.aidl??
  • package?com.pack;??
  • interface?IMyService{??
  • ????String?getValue();??
  • }??
  • ? ? ? ? 這個文件中只有一個方法getValue(),然后我們來看系統為其生成的Java文件: [java]?view plaincopy
  • @IMyService.java??
  • package?com.pack;??
  • public?interface?IMyService?extends?android.os.IInterface?{??
  • ????//Stub繼承自Binder,并且實現了IMyService的接口??
  • ????public?static?abstract?class?Stub?extends?android.os.Binder?implements?com.pack.IMyService?{??
  • ????}??
  • }??
  • ? ? ? ? 從生成的Java文件可以看出,IMyService.Stub是android.os.Binder的子類,而android.os.Binder又是IBinder的子類: [java]?view plaincopy
  • @Binder.java(google-code\frameworks\base\core\java\android\os\)??
  • public?class?Binder?implements?IBinder{}??
  • ? ? ? ? 由此我們推斷,IccPhoneBookInterfaceManagerProxy的父類IIccPhoneBook.Stub也是IBinder的子類。下面我們來看這個Service的使用方法。 [java]?view plaincopy
  • @IccProvider.java(google-code\frameworks\opt\telephony\src\java\com\android\internal\telephony\)??
  • private?boolean?addIccRecordToEf(int?efType,?String?name,?String?number,?String[]?emails,?String?pin2)?{??
  • ????boolean?success?=?false;??
  • ????try?{??
  • ????????//得到simphonebook的Service??
  • ????????IIccPhoneBook?iccIpb?=?IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));??
  • ????????if?(iccIpb?!=?null)?{??
  • ????????????//添加SIM卡聯系人??
  • ????????????success?=?iccIpb.updateAdnRecordsInEfBySearch(efType,?"",?"",?name,?number,?pin2);??
  • ????????}??
  • ????}?catch?(RemoteException?ex)?{??
  • ????}?catch?(SecurityException?ex)?{??
  • ????}??
  • ????return?success;??
  • }??
  • ? ? ? ? 上面這個方法的作用就是向SIM卡中添加聯系人的操作,在這個操作過程中, 先要通過Java層的ServiceManager得到"simphonebook"的Service,然后通過asInterface()方法將得到的Service對象轉換成客戶端可以直接調用的代理對象,然后再調用該代理對象的的updateAdnRecordsInEfBySearch()方法
    ? ? ? ? 下面我們將上述動作分解為3步來分析:
    ? ? ? ?? 1、通過ServiceManager得到simphonebook的BpBinder對象
    ? ? ? ? 2、通過asInterface()方法得到simphonebook這個Service的Java層代理對象

    3.1、通過ServiceManager得到simphonebook的BpBinder對象

    ? ? ? ? 在這一步中,我們來分析ServiceManager.getService("simphonebook")的過程。
    ? ? ? ? 我們先來看ServiceManager的getService()方法: [java]?view plaincopy
  • @ServiceManager.java??
  • public?static?IBinder?getService(String?name)?{??
  • ????try?{??
  • ????????IBinder?service?=?sCache.get(name);??
  • ????????if?(service?!=?null)?{??
  • ????????????return?service;??
  • ????????}?else?{??
  • ????????????//調用的是getIServiceManager()對象的getService()方法??
  • ????????????return?getIServiceManager().getService(name);??
  • ????????}??
  • ????}?catch?(RemoteException?e)?{??
  • ????}??
  • ????return?null;??
  • }??
  • private?static?IServiceManager?getIServiceManager()?{??
  • ????if?(sServiceManager?!=?null)?{??
  • ????????return?sServiceManager;??
  • ????}??
  • ????//通過getIServiceManager得到的其實是ServiceManager的Java層代理對象??
  • ????sServiceManager?=?ServiceManagerNative.asInterface(BinderInternal.getContextObject());??
  • ????return?sServiceManager;??
  • }??
  • ? ? ? ? 在2.2節中我們介紹過,在getIServiceManager()中得到的對象,就是ServiceManager在Java層的代理對象:ServiceManagerProxy。
    ? ? ? ? 那么調用該代理對象的getService()方法將會得到什么呢? [java]?view plaincopy
  • @ServiceManagerNative.java??
  • class?ServiceManagerProxy?implements?IServiceManager?{??
  • ????//ServiceManagerProxy的getService()方法??
  • ????public?IBinder?getService(String?name)?throws?RemoteException?{??
  • ????????Parcel?data?=?Parcel.obtain();??
  • ????????Parcel?reply?=?Parcel.obtain();??
  • ????????data.writeInterfaceToken(IServiceManager.descriptor);??
  • ????????data.writeString(name);??
  • ????????//這里的mRemote就是ServiceManager的BpBinder對象??
  • ????????mRemote.transact(GET_SERVICE_TRANSACTION,?data,?reply,?0);??
  • ????????IBinder?binder?=?reply.readStrongBinder();??
  • ????????reply.recycle();??
  • ????????data.recycle();??
  • ????????return?binder;??
  • ????}??
  • }??
  • ? ? ? ? 我們看到,ServiceManagerProxy將會把我們的請求(getService)轉交給Native層的ServiceManager的BpBinder對象,而在《Binder源碼分析之Native層》一文中我們分析過,Native層的ServiceManager得到這種請求后,將會把目標Service的BpBinder對象返回給客戶端。
    ? ? ? ? 也就是說, 經過Java層的ServiceManager.getService("simphonebook")操作,我們得到了simphonebook這個Service的BpBinder對象

    3.2、通過asInterface()方法得到simphonebook這個Service的Java層代理對象

    ? ? ? ? 經過3.1的過程,我們得到了simphonebook的BpBinder對象,接下來我們將要分析,如何通過該對象得到simphonebook這個Service的Java層可用的代理對象。
    ? ? ? ? 我們先將代碼簡化一下: [java]?view plaincopy
  • IIccPhoneBook?iccIpb?=?IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));??
  • ? ? ? ? 上面的代碼相當于: [java]?view plaincopy
  • IIccPhoneBook?iccIpb?=?IIccPhoneBook.Stub.asInterface(BpBinder("simphonebook"));??
  • ? ? ? ? 接下來的分析,我們就要繼續看生成的IIccPhoneBook.java文件了,我們還是借助剛剛生成的IMyService.java文件來看其asInterface()接口: [java]?view plaincopy
  • @IMyService.java??
  • public?interface?IMyService?extends?android.os.IInterface?{??
  • ????public?static?abstract?class?Stub?extends?android.os.Binder?implements?com.pack.IMyService?{??
  • ??
  • ????????public?static?com.pack.IMyService?asInterface(android.os.IBinder?obj)?{??
  • ????????????if?((obj?==?null))?{??
  • ????????????????return?null;??
  • ????????????}??
  • ????????????android.os.IInterface?iin?=?obj.queryLocalInterface(DESCRIPTOR);??
  • ????????????if?(((iin?!=?null)?&&?(iin?instanceof?com.pack.IMyService)))?{??
  • ????????????????return?((com.pack.IMyService)?iin);??
  • ????????????}??
  • ????????????//通過asInterface()得到的是Proxy對象,并且把BpBinder對象作為參數傳遞進去??
  • ????????????return?new?com.pack.IMyService.Stub.Proxy(obj);??
  • ????????}??
  • ??
  • ????????//代理類Proxy繼承自IMyService.aidl,需要實現里面的所有接口??
  • ????????private?static?class?Proxy?implements?com.pack.IMyService?{??
  • ????????????private?android.os.IBinder?mRemote;??
  • ????????????//保存得到的BpBinder對象??
  • ????????????Proxy(android.os.IBinder?remote)?{??
  • ????????????????mRemote?=?remote;??
  • ????????????}??
  • ??
  • ????????????@Override??
  • ????????????public?java.lang.String?getValue()?throws?android.os.RemoteException?{??
  • ????????????}??
  • ????????}??
  • ??
  • ????????static?final?int?TRANSACTION_getValue?=?(android.os.IBinder.FIRST_CALL_TRANSACTION?+?0);??
  • ????}??
  • ????public?java.lang.String?getValue()?throws?android.os.RemoteException;??
  • }??
  • ? ? ? ? 原來,我們通過IMyService.Stub.asInterface()得到的是一個Proxy的代理對象,這個對象是IMyService.Stub的內部類,也是IMyService的子類,需要實現IMyService.aidl文件中定義的方法。
    ? ? ? ? 把IMyService換成IIccPhoneBook,我們可以推測,通過IIccPhoneBook.Stub.asInterface(BpBinder)的操作,我們得到的是iccIpb.Stub的內部類Proxy對象,而且在這個類的內部擁有IIccPhoneBook.aidl文件定義的接口。 客戶端可以把這個代理類當作服務端對象一樣去調用AIDL中定義的所有方法
    ? ? ? ? 下面我們用圖來總結一下客戶端得到服務端的過程:



    四、客戶端調用Service方法的過程

    ? ? ? ? 經過3.2節的分析我們知道,通過IIccPhoneBook.Stub.asInterface()我們得到了一個服務端的代理對象:IIccPhoneBook.Stub.Proxy,我們可以直接調用IIccPhoneBook.aidl中定義的接口,那么這個代理類如何把接口的調用傳遞給服務端呢?服務器又是如何把數據返回給客戶端的呢?
    ? ? ? ? 現在我們先借用IMyService去分析其調用過程,最后再把過程擴大到其他的Java層Service調用過程中。
    ? ? ? ? 假如客戶端調用了IMyService.aidl中的getValue()方法(我們的IMyService.aidl文件中只有這一個方法),那么就會調用到Proxy類的內部: [java]?view plaincopy
  • private?static?class?Proxy?implements?com.pack.IMyService?{??
  • ????private?android.os.IBinder?mRemote;??
  • ??
  • ????Proxy(android.os.IBinder?remote)?{??
  • ????????mRemote?=?remote;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?java.lang.String?getValue()?throws?android.os.RemoteException?{??
  • ????????//準備Parcel數據??
  • ????????android.os.Parcel?_data?=?android.os.Parcel.obtain();??
  • ????????android.os.Parcel?_reply?=?android.os.Parcel.obtain();??
  • ????????java.lang.String?_result;??
  • ????????try?{??
  • ????????????_data.writeInterfaceToken(DESCRIPTOR);??
  • ????????????//調用mRemote的transact()方法發送數據,并且標記當前調用的方法為getValue??
  • ????????????mRemote.transact(Stub.TRANSACTION_getValue,?_data,?_reply,?0);??
  • ????????????//提取服務端的返回值??
  • ????????????_reply.readException();??
  • ????????????_result?=?_reply.readString();??
  • ????????}?finally?{??
  • ????????????_reply.recycle();??
  • ????????????_data.recycle();??
  • ????????}??
  • ????????return?_result;??
  • ????}??
  • }??
  • ? ? ? ? 在Proxy的getValue()方法中,將客戶端的請求封裝為Parcel類型的數據通過mRemote變量發送出去,而且在發送時標記了當前的命令是TRANSACTION_getValue,也就是調用getValue方法,那么這里的mRemote對象是什么呢?
    ? ? ? ? 還記得在創建Proxy類的時候我們是把目標Service的BpBinder對象傳遞給了mRemote變量,那么這里的transact()就會調用到BpBinder中: [java]?view plaincopy
  • @BpBinder.cpp??
  • status_t?BpBinder::transact(?uint32_t?code,?const?Parcel&?data,?Parcel*?reply,?uint32_t?flags)?{??
  • ????if?(mAlive)?{??
  • ????????//向Service發送請求??
  • ????????status_t?status?=?IPCThreadState::self()->transact(?mHandle,?code,?data,?reply,?flags);??
  • ????????if?(status?==?DEAD_OBJECT)?mAlive?=?0;??
  • ????????return?status;??
  • ????}??
  • ????return?DEAD_OBJECT;??
  • }??
  • ? ? ? ? 接下來就是Native層的流程了。看來Proxy代理的作用就是在客戶端調用各種方法時,將方法編號(TRANSACTION_getValue)后通過目標Service的BpBinder對象向Native層的Binder機制發送(transact)請求,同時準備在reply中接收服務端的返回值。
    ? ? ? ? 而根據《Binder源碼分析之Native層》中的分析,服務端在接收到客戶端請求后,最終會調用到服務端父類BBinder的transact()方法: [java]?view plaincopy
  • @Binder.cpp??
  • status_t?BBinder::transact(?uint32_t?code,?const?Parcel&?data,?Parcel*?reply,?uint32_t?flags)?{??
  • ????status_t?err?=?NO_ERROR;??
  • ????switch?(code)?{??
  • ????????case?PING_TRANSACTION:??
  • ????????????reply->writeInt32(pingBinder());??
  • ????????????break;??
  • ????????default:??
  • ????????????//調用BBinder的子類去處理當前請求??
  • ????????????err?=?onTransact(code,?data,?reply,?flags);??
  • ????????????break;??
  • ????}??
  • ????return?err;??
  • }??
  • ? ? ? ? 我們看到,在BBinder的transact()方法中,將會調用Service的onTransact()的方法,由于當前的IMyService就是BBinder的子類,因此這里的onTransact()方法將會進入到IMyService的內部,也就是: [java]?view plaincopy
  • public?interface?IMyService?extends?android.os.IInterface?{??
  • ????public?static?abstract?class?Stub?extends?android.os.Binder?implements?com.pack.IMyService?{??
  • ????????public?boolean?onTransact(int?code,?android.os.Parcel?data,?android.os.Parcel?reply,?int?flags)?throws?android.os.RemoteException?{??
  • ????????????switch?(code)?{??
  • ????????????????case?INTERFACE_TRANSACTION:?{??
  • ????????????????????reply.writeString(DESCRIPTOR);??
  • ????????????????????return?true;??
  • ????????????????}??
  • ????????????????case?TRANSACTION_getValue:?{??
  • ????????????????????//客戶端發起的getValue()的請求??
  • ????????????????????data.enforceInterface(DESCRIPTOR);??
  • ????????????????????//繼續調用子類的getValue()方法??
  • ????????????????????java.lang.String?_result?=?this.getValue();??
  • ????????????????????reply.writeNoException();??
  • ????????????????????reply.writeString(_result);??
  • ????????????????????return?true;??
  • ????????????????}??
  • ????????????}??
  • ????????????return?super.onTransact(code,?data,?reply,?flags);??
  • ????????}??
  • ????????static?final?int?TRANSACTION_getValue?=?(android.os.IBinder.FIRST_CALL_TRANSACTION?+?0);??
  • ????}??
  • ????public?java.lang.String?getValue()?throws?android.os.RemoteException;??
  • }??
  • ? ? ? ? 我們看到在onTransact()中將會繼續調用子類的getValue()方法,而這里的IMyService.Stub的子類,當然就是客戶端本身了。如果結合IIccPhoneBook的服務端來看,當在IIccPhoneBook.Stub中調用其onTransact()方法時,就會在相應的TRANSACTION_xxx分支中調用到IccPhoneBookInterfaceManagerProxy.java中的各個方法,這樣也就完成了從客戶端到服務端的調用過程。
    ? ? ? ? 那么,當客戶端調用的方法需要返回值時,服務端是如何把返回值傳回給客戶端的呢?
    ? ? ? ? 我們還來看getValue()的過程,這個方法當然需要服務端提供返回值,因此在onTransact()調用到子類的this.getValue()時,就會得到服務端的返回值,接下來我們看到,在TRANSACTION_getValue分支中會把返回值(_result)放入reply中,接著就結束了onTransact()的調用。
    ? ? ? ? 也就是說, 在服務端的onTransact()過程中,不僅完成了對服務端的調用,而且也帶回來了服務端的返回值,這個返回值是通過onTransact()的參數傳遞出去的
    ? ? ? ? 然后當BBinder的onTransact()結束后,就返回到了BBinder的transact()操作中,接著再層層返回,并經過Native層Binder的傳輸,再次回到BpBinder的transact()中,然后等BpBinder的transact()返回后,我們就再次回到了IMyService.java中的getValue()方法: [java]?view plaincopy
  • public?java.lang.String?getValue()?throws?android.os.RemoteException?{??
  • ????android.os.Parcel?_data?=?android.os.Parcel.obtain();??
  • ????android.os.Parcel?_reply?=?android.os.Parcel.obtain();??
  • ????java.lang.String?_result;??
  • ????try?{??
  • ????????_data.writeInterfaceToken(DESCRIPTOR);??
  • ????????//經歷了一次漫長的跨進程調用過程??
  • ????????mRemote.transact(Stub.TRANSACTION_getValue,?_data,?_reply,?0);??
  • ????????_reply.readException();??
  • ????????_result?=?_reply.readString();??
  • ????}?finally?{??
  • ????????_reply.recycle();??
  • ????????_data.recycle();??
  • ????}??
  • ????return?_result;??
  • }??
  • ? ? ? ? 此時的mRemote.transact()方法已經調用結束,他不僅發起了對服務端的請求,而且帶回了服務端的返回值,最后,經過return語句將返回值傳遞給了客戶端。
    ? ? ? ? 如果結合這IIccPhoneBook來分析,此時的調用將會從IIccPhoneBook.Stub中返回到其子類中也就是IccProvider中,從而完成了客戶端的調用過程。
    ? ? ? ? 也就是說, 我們在IccProvider對客戶端的調用經過IIccPhoneBook傳遞到Native層,然后又經過IccProvider傳遞給Service的實現者IccPhoneBookInterfaceManagerProxy。完成請求后,再經過逆過程回到IccProvider客戶端中
    ? ? ? ? 這就是Java層的Binder調用過程。
    ? ? ? ? 最后,用一張圖來示意客戶端調用服務端的過程:




    原文地址:http://blog.csdn.net/u010961631/article/details/20691793

    總結

    以上是生活随笔為你收集整理的Binder源码分析之Java层(原)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。