Binder源码分析之Java层(原)
生活随笔
收集整理的這篇文章主要介紹了
Binder源码分析之Java层(原)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?? ? ? 前面的幾節(jié)中我們介紹了Native層Binder通訊的原理和用法,那么在Java層如何使用Binder通訊呢?其原理又與Native層的Binder有什么關(guān)系呢?
? ? ? ? 與Native層的ServiceManager類似,Android在Java層也有一個(gè)ServiceManager用于處理Java層Service的注冊、申請。只不過, Java層的這個(gè)ServiceManager,其實(shí)是在Java層建立的ServiceManager的代理,他把Java層客戶端的各項(xiàng)請求傳遞到Native層的ServiceManager進(jìn)行處理 。
? ? ? ? 而對于其他Java層的Service來說,客戶端得到的Service遠(yuǎn)程代理對象,就是Native層得到的BpXXXService對象。
? ? ? ? 接下來我們分四部分來介紹Java層Binder機(jī)制:
? ? ? ?? 1、ServiceManager的結(jié)構(gòu) ;
? ? ? ?? 2、如何注冊一個(gè)Service ;
? ? ? ?? 3、如何得到一個(gè)Service ;
@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)?{?? ????}?? }??
@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);?? ????????????//調(diào)用ServiceManager注冊服務(wù)?? ????????????ServiceManager.addService(Context.STATUS_BAR_SERVICE,?statusBar);?? ????????}?catch?(Throwable?e)?{?? ????????????reportWtf("starting?StatusBarManagerService",?e);?? ????????}?? ????}?? }??
? ? ? ? 我們看到,作為一個(gè)Service,可以通過調(diào)用ServiceManager的addService()方法注冊自己。注冊的時(shí)候傳遞了兩個(gè)參數(shù),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()內(nèi)部,把a(bǔ)ddService()的請求轉(zhuǎn)發(fā)給了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()可以得到一個(gè)IServiceManager類型的sServiceManager對象,
那么這個(gè)對象究竟是什么屬性的呢
?
? ? ? ? 其實(shí) 我們通過getIServiceManager()得到的就是Java層中的ServiceManager的代理對象ServiceManagerProxy 。為了得到這個(gè)對象,我們需要經(jīng)過兩步的準(zhǔn)備:
? ? ? ?? 1、通過Native層的調(diào)用得到ServiceManager的遠(yuǎn)程對象BpBinder
? ? ? ? ? ? ----也就是BinderInternal.getContextObject()的操作
? ? ? ? ?2、把ServiceManager的BpBinder封裝為Java層可用的ServiceManagerProxy對象
? ? ? ? ? ? ----也就是ServiceManagerNative().asInterface()的操作
? ? ? ? 下面我們來詳細(xì)分析這兩個(gè)步驟
@BinderInternal.java(google-code\frameworks\base\core\java\com\android\internal\os\BinderInternal.java)?? public?static?final?native?IBinder?getContextObject();??
? ? ? ? 他的聲明方式說明這個(gè)方法是在Native中被實(shí)現(xiàn)的,那么他具體定義是在哪里呢?
? ? ? ? 我們簡單來說一下流程。
? ? ? ? 在Java虛擬機(jī)啟動時(shí),將會注冊一系列的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;?? ????}?? }??
? ? ? ? 在虛擬機(jī)啟動時(shí),將會通過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列表并注冊,我們來看需要注冊的列表內(nèi)容:
[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進(jìn)行注冊:
[java]?view plaincopy static?int?int_register_android_os_BinderInternal(JNIEnv*?env)?{?? ????jclass?clazz;?? ????//根據(jù)路徑找到類?? ????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?}?? };??
? ? ? ? 這個(gè)數(shù)組中就定義了getContextObject方法所對應(yīng)的jni實(shí)現(xiàn),其實(shí)就是android_os_BinderInternal_getContextObject(),也就是說,getContextObject()將會調(diào)用到android_os_BinderInternal_getContextObject(),我們看一下這個(gè)方法的定義:
[java]?view plaincopy static?jobject?android_os_BinderInternal_getContextObject(JNIEnv*?env,?jobject?clazz)?{?? ????//得到BpBinder(0)對象?? ????sp<IBinder>?b?=?ProcessState::self()->getContextObject(NULL);?? ????//將BpBinder對象轉(zhuǎn)換為Java對象?? ????return?javaObjectForIBinder(env,?b);?? }??
? ? ? ? 在這個(gè)方法中,完成了兩步重要的操作:
? ? ? ?? 1、通過ProcessState的getContextObject(NULL)得到了ServiceManager的BpBinder(0)對象 (詳細(xì)過程在《Binder源碼分析之Native層》中做過詳細(xì)介紹)。
? ? ? ?? 2、通過javaObjectForIBinder()方法把得到的BpBinder對象封裝成Java層可用的類型 。
? ? ? ? 至此,我們就拿到了Java層可用的ServiceManager的BpBinder對象, 下面要做的就是把該對象轉(zhuǎn)換為Java層可用的ServiceManager代理對象 。
private?static?IServiceManager?getIServiceManager()?{?? ????if?(sServiceManager?!=?null)?{?? ????????//單例模式?? ????????return?sServiceManager;?? ????}?? ????//得到ServiceManager的Java層代理對象?? ????sServiceManager?=?ServiceManagerNative.asInterface(BinderInternal.getContextObject());?? ????return?sServiceManager;?? }??
? ? ? ? 經(jīng)過前面2.1的分析,我們了解了通過BinderInternal.getContextObject()可以得到BpBinder(0)的Java層代理對象,接下來就需要
調(diào)用ServiceManagerNative的asInterface()方法將該對象轉(zhuǎn)換為Java層可用的ServiceManager代理對象
。
? ? ? ? 也就是說,當(dāng)前的getIServiceManager()相當(dāng)于: [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;?? ????}?? ????//創(chuàng)建代理對象?? ????return?new?ServiceManagerProxy(obj);?? }??
? ? ? ? 我們看到,通過asInterface()的轉(zhuǎn)換,
我們用BpBinder對象生成了ServiceManagerProxy對象
。
? ? ? ? 也就是說, 通過getIServiceManager()得到的sServiceManager對象,其實(shí)是ServiceManagerProxy對象 。
class?ServiceManagerProxy?implements?IServiceManager?{}??
? ? ? ? 從繼承關(guān)系上來看,
ServiceManagerProxy實(shí)現(xiàn)了IServiceManager中定義的接口
。
? ? ? ? 然后再來看其構(gòu)造函數(shù),在2.2中介紹過,創(chuàng)建ServiceManagerProxy對象時(shí),是用ServiceManager的BpBinder對象作為參數(shù)的: [java]?view plaincopy public?ServiceManagerProxy(IBinder?remote)?{?? ????mRemote?=?remote;?? }??
? ? ? ? 這里的構(gòu)造函數(shù)中,把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確實(shí)實(shí)現(xiàn)了IServiceManager中的方法,提供了add、get、check、list等功能。
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的時(shí)候,將當(dāng)前Service的name和service對象封裝到Parcel類型的data中,然后調(diào)用mRemote對象的transact()方法發(fā)送出去,并標(biāo)記當(dāng)前的操作是“ADD_SERVICE_TRANSACTION”,還記得我們在分析ServiceManagerProxy的構(gòu)造函數(shù)時(shí)傳遞的參數(shù)其實(shí)是BpBinder對象,那么這里的transact()就會調(diào)用到BpBinder中:
[java]?view plaincopy @BpBinder.cpp?? status_t?BpBinder::transact(?uint32_t?code,?const?Parcel&?data,?Parcel*?reply,?uint32_t?flags)?{?? ????if?(mAlive)?{?? ????????//進(jìn)入IPCThreadState繼續(xù)調(diào)用?? ????????status_t?status?=?IPCThreadState::self()->transact(?mHandle,?code,?data,?reply,?flags);?? ????????if?(status?==?DEAD_OBJECT)?mAlive?=?0;?? ????????return?status;?? ????}?? ????return?DEAD_OBJECT;?? }??
? ? ? ? 到這里,就進(jìn)入了Native層Binder的使用了,接下來就是經(jīng)過IPCThreadState把請求發(fā)送到Binder驅(qū)動,然后在ServiceManager的進(jìn)程中檢測到請求并處理,這個(gè)過程在Native層分析時(shí)詳細(xì)介紹過,這里就不再分析了。
? ? ? ? 經(jīng)過以上的分析,我們對Java層ServiceManager有了全新的認(rèn)識, 簡單來說,Java層的ServiceManager就是Native層ServiceManager的一個(gè)Client,而對于Java層其他Service來說,Java層的ServiceManager又是一個(gè)Service,負(fù)責(zé)把其他Client的請求轉(zhuǎn)發(fā)給Native層的ServiceManager去處理 。
? ? ? ? 而ServiceManagerProxy又是Java層ServiceManager的代理,其負(fù)責(zé)將Java層其他客戶端對ServiceManager的調(diào)用傳遞給Native層的ServiceManager。
? ? ? ? 這一次我們挑選simphonebook這個(gè)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的注冊過程,看似簡單,但是有個(gè)疑問,我們知道,在addService()的操作時(shí),必須傳遞2個(gè)參數(shù):name+IBinder子類對象,但是這里的this所指的IccPhoneBookInterfaceManagerProxy對象,是IBinder子類的對象嗎?
? ? ? ? 我們來看IccPhoneBookInterfaceManagerProxy這個(gè)類的繼承關(guān)系: [java]?view plaincopy public?class?IccPhoneBookInterfaceManagerProxy?extends?IIccPhoneBook.Stub?{}??
? ? ? ? 我們看到,他繼承了一個(gè)IIccPhoneBook.Stub的父類,這個(gè)父類是什么屬性呢?他和BBinder的子類嗎?
? ? ? ? 我們在代碼中找不到IIccPhoneBook.Stub的文件或類,但是找到了IIccPhoneBook.aidl文件,這個(gè)文件的作用又是什么呢?
? ? ? ? 原來,這里的 AIDL文件是Android中定義的接口語言(Android Interface Definition Language)。開發(fā)者只要按照指定的格式創(chuàng)建AIDL文件,系統(tǒng)就會自動為該文件生成一個(gè)對應(yīng)的Java文件 。
? ? ? ? 假如我們創(chuàng)建一個(gè)IMyService.aidl文件,其內(nèi)容為: [java]?view plaincopy @IMyService.aidl?? package?com.pack;?? interface?IMyService{?? ????String?getValue();?? }??
? ? ? ? 這個(gè)文件中只有一個(gè)方法getValue(),然后我們來看系統(tǒng)為其生成的Java文件:
[java]?view plaincopy @IMyService.java?? package?com.pack;?? public?interface?IMyService?extends?android.os.IInterface?{?? ????//Stub繼承自Binder,并且實(shí)現(xiàn)了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的子類。下面我們來看這個(gè)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卡聯(lián)系人?? ????????????success?=?iccIpb.updateAdnRecordsInEfBySearch(efType,?"",?"",?name,?number,?pin2);?? ????????}?? ????}?catch?(RemoteException?ex)?{?? ????}?catch?(SecurityException?ex)?{?? ????}?? ????return?success;?? }??
? ? ? ? 上面這個(gè)方法的作用就是向SIM卡中添加聯(lián)系人的操作,在這個(gè)操作過程中,
先要通過Java層的ServiceManager得到"simphonebook"的Service,然后通過asInterface()方法將得到的Service對象轉(zhuǎn)換成客戶端可以直接調(diào)用的代理對象,然后再調(diào)用該代理對象的的updateAdnRecordsInEfBySearch()方法
。
? ? ? ? 下面我們將上述動作分解為3步來分析:
? ? ? ?? 1、通過ServiceManager得到simphonebook的BpBinder對象
? ? ? ? 2、通過asInterface()方法得到simphonebook這個(gè)Service的Java層代理對象
? ? ? ? 我們先來看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?{?? ????????????//調(diào)用的是getIServiceManager()對象的getService()方法?? ????????????return?getIServiceManager().getService(name);?? ????????}?? ????}?catch?(RemoteException?e)?{?? ????}?? ????return?null;?? }?? private?static?IServiceManager?getIServiceManager()?{?? ????if?(sServiceManager?!=?null)?{?? ????????return?sServiceManager;?? ????}?? ????//通過getIServiceManager得到的其實(shí)是ServiceManager的Java層代理對象?? ????sServiceManager?=?ServiceManagerNative.asInterface(BinderInternal.getContextObject());?? ????return?sServiceManager;?? }??
? ? ? ? 在2.2節(jié)中我們介紹過,在getIServiceManager()中得到的對象,就是ServiceManager在Java層的代理對象:ServiceManagerProxy。
? ? ? ? 那么調(diào)用該代理對象的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)轉(zhuǎn)交給Native層的ServiceManager的BpBinder對象,而在《Binder源碼分析之Native層》一文中我們分析過,Native層的ServiceManager得到這種請求后,將會把目標(biāo)Service的BpBinder對象返回給客戶端。
? ? ? ? 也就是說, 經(jīng)過Java層的ServiceManager.getService("simphonebook")操作,我們得到了simphonebook這個(gè)Service的BpBinder對象 。
? ? ? ? 我們先將代碼簡化一下: [java]?view plaincopy IIccPhoneBook?iccIpb?=?IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));??
? ? ? ? 上面的代碼相當(dāng)于:
[java]?view plaincopy IIccPhoneBook?iccIpb?=?IIccPhoneBook.Stub.asInterface(BpBinder("simphonebook"));??
? ? ? ? 接下來的分析,我們就要繼續(xù)看生成的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對象作為參數(shù)傳遞進(jìn)去?? ????????????return?new?com.pack.IMyService.Stub.Proxy(obj);?? ????????}?? ?? ????????//代理類Proxy繼承自IMyService.aidl,需要實(shí)現(xiàn)里面的所有接口?? ????????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()得到的是一個(gè)Proxy的代理對象,這個(gè)對象是IMyService.Stub的內(nèi)部類,也是IMyService的子類,需要實(shí)現(xiàn)IMyService.aidl文件中定義的方法。
? ? ? ? 把IMyService換成IIccPhoneBook,我們可以推測,通過IIccPhoneBook.Stub.asInterface(BpBinder)的操作,我們得到的是iccIpb.Stub的內(nèi)部類Proxy對象,而且在這個(gè)類的內(nèi)部擁有IIccPhoneBook.aidl文件定義的接口。 客戶端可以把這個(gè)代理類當(dāng)作服務(wù)端對象一樣去調(diào)用AIDL中定義的所有方法 。
? ? ? ? 下面我們用圖來總結(jié)一下客戶端得到服務(wù)端的過程:
? ? ? ? 現(xiàn)在我們先借用IMyService去分析其調(diào)用過程,最后再把過程擴(kuò)大到其他的Java層Service調(diào)用過程中。
? ? ? ? 假如客戶端調(diào)用了IMyService.aidl中的getValue()方法(我們的IMyService.aidl文件中只有這一個(gè)方法),那么就會調(diào)用到Proxy類的內(nèi)部: [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?{?? ????????//準(zhǔn)備Parcel數(shù)據(jù)?? ????????android.os.Parcel?_data?=?android.os.Parcel.obtain();?? ????????android.os.Parcel?_reply?=?android.os.Parcel.obtain();?? ????????java.lang.String?_result;?? ????????try?{?? ????????????_data.writeInterfaceToken(DESCRIPTOR);?? ????????????//調(diào)用mRemote的transact()方法發(fā)送數(shù)據(jù),并且標(biāo)記當(dāng)前調(diào)用的方法為getValue?? ????????????mRemote.transact(Stub.TRANSACTION_getValue,?_data,?_reply,?0);?? ????????????//提取服務(wù)端的返回值?? ????????????_reply.readException();?? ????????????_result?=?_reply.readString();?? ????????}?finally?{?? ????????????_reply.recycle();?? ????????????_data.recycle();?? ????????}?? ????????return?_result;?? ????}?? }??
? ? ? ? 在Proxy的getValue()方法中,將客戶端的請求封裝為Parcel類型的數(shù)據(jù)通過mRemote變量發(fā)送出去,而且在發(fā)送時(shí)標(biāo)記了當(dāng)前的命令是TRANSACTION_getValue,也就是調(diào)用getValue方法,那么這里的mRemote對象是什么呢?
? ? ? ? 還記得在創(chuàng)建Proxy類的時(shí)候我們是把目標(biāo)Service的BpBinder對象傳遞給了mRemote變量,那么這里的transact()就會調(diào)用到BpBinder中: [java]?view plaincopy @BpBinder.cpp?? status_t?BpBinder::transact(?uint32_t?code,?const?Parcel&?data,?Parcel*?reply,?uint32_t?flags)?{?? ????if?(mAlive)?{?? ????????//向Service發(fā)送請求?? ????????status_t?status?=?IPCThreadState::self()->transact(?mHandle,?code,?data,?reply,?flags);?? ????????if?(status?==?DEAD_OBJECT)?mAlive?=?0;?? ????????return?status;?? ????}?? ????return?DEAD_OBJECT;?? }??
? ? ? ? 接下來就是Native層的流程了??磥鞵roxy代理的作用就是在客戶端調(diào)用各種方法時(shí),將方法編號(TRANSACTION_getValue)后通過目標(biāo)Service的BpBinder對象向Native層的Binder機(jī)制發(fā)送(transact)請求,同時(shí)準(zhǔn)備在reply中接收服務(wù)端的返回值。
? ? ? ? 而根據(jù)《Binder源碼分析之Native層》中的分析,服務(wù)端在接收到客戶端請求后,最終會調(diào)用到服務(wù)端父類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:?? ????????????//調(diào)用BBinder的子類去處理當(dāng)前請求?? ????????????err?=?onTransact(code,?data,?reply,?flags);?? ????????????break;?? ????}?? ????return?err;?? }??
? ? ? ? 我們看到,在BBinder的transact()方法中,將會調(diào)用Service的onTransact()的方法,由于當(dāng)前的IMyService就是BBinder的子類,因此這里的onTransact()方法將會進(jìn)入到IMyService的內(nèi)部,也就是:
[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:?{?? ????????????????????//客戶端發(fā)起的getValue()的請求?? ????????????????????data.enforceInterface(DESCRIPTOR);?? ????????????????????//繼續(xù)調(diào)用子類的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()中將會繼續(xù)調(diào)用子類的getValue()方法,而這里的IMyService.Stub的子類,當(dāng)然就是客戶端本身了。如果結(jié)合IIccPhoneBook的服務(wù)端來看,當(dāng)在IIccPhoneBook.Stub中調(diào)用其onTransact()方法時(shí),就會在相應(yīng)的TRANSACTION_xxx分支中調(diào)用到IccPhoneBookInterfaceManagerProxy.java中的各個(gè)方法,這樣也就完成了從客戶端到服務(wù)端的調(diào)用過程。
? ? ? ? 那么,當(dāng)客戶端調(diào)用的方法需要返回值時(shí),服務(wù)端是如何把返回值傳回給客戶端的呢?
? ? ? ? 我們還來看getValue()的過程,這個(gè)方法當(dāng)然需要服務(wù)端提供返回值,因此在onTransact()調(diào)用到子類的this.getValue()時(shí),就會得到服務(wù)端的返回值,接下來我們看到,在TRANSACTION_getValue分支中會把返回值(_result)放入reply中,接著就結(jié)束了onTransact()的調(diào)用。
? ? ? ? 也就是說, 在服務(wù)端的onTransact()過程中,不僅完成了對服務(wù)端的調(diào)用,而且也帶回來了服務(wù)端的返回值,這個(gè)返回值是通過onTransact()的參數(shù)傳遞出去的 。
? ? ? ? 然后當(dāng)BBinder的onTransact()結(jié)束后,就返回到了BBinder的transact()操作中,接著再層層返回,并經(jīng)過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);?? ????????//經(jīng)歷了一次漫長的跨進(jìn)程調(diào)用過程?? ????????mRemote.transact(Stub.TRANSACTION_getValue,?_data,?_reply,?0);?? ????????_reply.readException();?? ????????_result?=?_reply.readString();?? ????}?finally?{?? ????????_reply.recycle();?? ????????_data.recycle();?? ????}?? ????return?_result;?? }??
? ? ? ? 此時(shí)的mRemote.transact()方法已經(jīng)調(diào)用結(jié)束,他不僅發(fā)起了對服務(wù)端的請求,而且?guī)Щ亓朔?wù)端的返回值,最后,經(jīng)過return語句將返回值傳遞給了客戶端。
? ? ? ? 如果結(jié)合這IIccPhoneBook來分析,此時(shí)的調(diào)用將會從IIccPhoneBook.Stub中返回到其子類中也就是IccProvider中,從而完成了客戶端的調(diào)用過程。
? ? ? ? 也就是說, 我們在IccProvider對客戶端的調(diào)用經(jīng)過IIccPhoneBook傳遞到Native層,然后又經(jīng)過IccProvider傳遞給Service的實(shí)現(xiàn)者IccPhoneBookInterfaceManagerProxy。完成請求后,再經(jīng)過逆過程回到IccProvider客戶端中 。
? ? ? ? 這就是Java層的Binder調(diào)用過程。
? ? ? ? 最后,用一張圖來示意客戶端調(diào)用服務(wù)端的過程:
? ? ? ? 與Native層的ServiceManager類似,Android在Java層也有一個(gè)ServiceManager用于處理Java層Service的注冊、申請。只不過, Java層的這個(gè)ServiceManager,其實(shí)是在Java層建立的ServiceManager的代理,他把Java層客戶端的各項(xiàng)請求傳遞到Native層的ServiceManager進(jìn)行處理 。
? ? ? ? 而對于其他Java層的Service來說,客戶端得到的Service遠(yuǎn)程代理對象,就是Native層得到的BpXXXService對象。
? ? ? ? 接下來我們分四部分來介紹Java層Binder機(jī)制:
? ? ? ?? 1、ServiceManager的結(jié)構(gòu) ;
? ? ? ?? 2、如何注冊一個(gè)Service ;
? ? ? ?? 3、如何得到一個(gè)Service ;
? ? ? ??4、Service代理對象方法的過程;
一、ServiceManager的結(jié)構(gòu)
? ? ? ? 我們來看一下ServiceManager類的代碼: [java]?view plaincopy? ? ? ? 這個(gè)類比較簡單,而且我們看到,ServiceManager沒有繼承任何的類,那么他是如何實(shí)現(xiàn)“管理員”的角色呢?
二、如何在Java層通過ServiceManager注冊一個(gè)Service
? ? ? ? Android啟動時(shí),將會在SystemServer中的ServerThread線程中將一些重要的Java層Service注冊并啟動,我們在這里挑選負(fù)責(zé)狀態(tài)欄管理的StatusBarManagerService來分析。 [java]?view plaincopy? ? ? ? 我們來看ServiceManager的addService()方法: [java]?view plaincopy
? ? ? ? 其實(shí) 我們通過getIServiceManager()得到的就是Java層中的ServiceManager的代理對象ServiceManagerProxy 。為了得到這個(gè)對象,我們需要經(jīng)過兩步的準(zhǔn)備:
? ? ? ?? 1、通過Native層的調(diào)用得到ServiceManager的遠(yuǎn)程對象BpBinder
? ? ? ? ? ? ----也就是BinderInternal.getContextObject()的操作
? ? ? ? ?2、把ServiceManager的BpBinder封裝為Java層可用的ServiceManagerProxy對象
? ? ? ? ? ? ----也就是ServiceManagerNative().asInterface()的操作
? ? ? ? 下面我們來詳細(xì)分析這兩個(gè)步驟
2.1、得到ServiceManager的BpBinder對象過程
? ? ? ? 這一步中我們將會看到, 如何通過BinderInternal.getContextObject()得到ServiceManager的BpBinder()對象 ,下面我們來看這個(gè)方法的聲明: [java]?view plaincopy? ? ? ? 我們簡單來說一下流程。
? ? ? ? 在Java虛擬機(jī)啟動時(shí),將會注冊一系列的native方法 [java]?view plaincopy
? ? ? ?? 1、通過ProcessState的getContextObject(NULL)得到了ServiceManager的BpBinder(0)對象 (詳細(xì)過程在《Binder源碼分析之Native層》中做過詳細(xì)介紹)。
? ? ? ?? 2、通過javaObjectForIBinder()方法把得到的BpBinder對象封裝成Java層可用的類型 。
? ? ? ? 至此,我們就拿到了Java層可用的ServiceManager的BpBinder對象, 下面要做的就是把該對象轉(zhuǎn)換為Java層可用的ServiceManager代理對象 。
2.2、用BpBinder得到ServiceManagerProxy對象過程
? ? ? ? 我們在第二節(jié)剛開始的地方介紹過,Service注冊自己的時(shí)候需要在ServiceManager中通過getIServiceManager()方法得到ServiceManager在Java層的代理對象,然后調(diào)用該對象的addService()方法完成注冊: [java]?view plaincopy? ? ? ? 也就是說,當(dāng)前的getIServiceManager()相當(dāng)于: [java]?view plaincopy
? ? ? ? 也就是說, 通過getIServiceManager()得到的sServiceManager對象,其實(shí)是ServiceManagerProxy對象 。
2.3、ServiceManagerProxy對象
? ? ? ? 我們先來看一下其繼承結(jié)構(gòu): [java]?view plaincopy? ? ? ? 然后再來看其構(gòu)造函數(shù),在2.2中介紹過,創(chuàng)建ServiceManagerProxy對象時(shí),是用ServiceManager的BpBinder對象作為參數(shù)的: [java]?view plaincopy
? ? ? ? 下面我們來看ServiceManagerProxy中的方法: [java]?view plaincopy
2.4、注冊Service的過程
? ? ? ? 經(jīng)過以上的分析,我們知道通過getIServiceManager()的調(diào)用,我們得到的是ServiceManagerProxy對象,那么當(dāng)注冊Service時(shí)調(diào)用的addService()方法就會調(diào)用到ServiceManagerProxy中: [java]?view plaincopy? ? ? ? 經(jīng)過以上的分析,我們對Java層ServiceManager有了全新的認(rèn)識, 簡單來說,Java層的ServiceManager就是Native層ServiceManager的一個(gè)Client,而對于Java層其他Service來說,Java層的ServiceManager又是一個(gè)Service,負(fù)責(zé)把其他Client的請求轉(zhuǎn)發(fā)給Native層的ServiceManager去處理 。
? ? ? ? 而ServiceManagerProxy又是Java層ServiceManager的代理,其負(fù)責(zé)將Java層其他客戶端對ServiceManager的調(diào)用傳遞給Native層的ServiceManager。
? ? ? ? 下面用一張圖來示意Java層ServiceManager和Native層ServiceManager的關(guān)系:
? ??
三、客戶端如何得到一個(gè)Service
? ? ? ? 前面分析了如何在Java層注冊一個(gè)Service,下面我們來分析,如何在Java層得到某個(gè)Service服務(wù)。? ? ? ? 這一次我們挑選simphonebook這個(gè)Service來分析,先簡單來看一下其注冊成為Service的過程: [java]?view plaincopy
? ? ? ? 我們來看IccPhoneBookInterfaceManagerProxy這個(gè)類的繼承關(guān)系: [java]?view plaincopy
? ? ? ? 我們在代碼中找不到IIccPhoneBook.Stub的文件或類,但是找到了IIccPhoneBook.aidl文件,這個(gè)文件的作用又是什么呢?
? ? ? ? 原來,這里的 AIDL文件是Android中定義的接口語言(Android Interface Definition Language)。開發(fā)者只要按照指定的格式創(chuàng)建AIDL文件,系統(tǒng)就會自動為該文件生成一個(gè)對應(yīng)的Java文件 。
? ? ? ? 假如我們創(chuàng)建一個(gè)IMyService.aidl文件,其內(nèi)容為: [java]?view plaincopy
? ? ? ? 下面我們將上述動作分解為3步來分析:
? ? ? ?? 1、通過ServiceManager得到simphonebook的BpBinder對象
? ? ? ? 2、通過asInterface()方法得到simphonebook這個(gè)Service的Java層代理對象
3.1、通過ServiceManager得到simphonebook的BpBinder對象
? ? ? ? 在這一步中,我們來分析ServiceManager.getService("simphonebook")的過程。? ? ? ? 我們先來看ServiceManager的getService()方法: [java]?view plaincopy
? ? ? ? 那么調(diào)用該代理對象的getService()方法將會得到什么呢? [java]?view plaincopy
? ? ? ? 也就是說, 經(jīng)過Java層的ServiceManager.getService("simphonebook")操作,我們得到了simphonebook這個(gè)Service的BpBinder對象 。
3.2、通過asInterface()方法得到simphonebook這個(gè)Service的Java層代理對象
? ? ? ? 經(jīng)過3.1的過程,我們得到了simphonebook的BpBinder對象,接下來我們將要分析,如何通過該對象得到simphonebook這個(gè)Service的Java層可用的代理對象。? ? ? ? 我們先將代碼簡化一下: [java]?view plaincopy
? ? ? ? 把IMyService換成IIccPhoneBook,我們可以推測,通過IIccPhoneBook.Stub.asInterface(BpBinder)的操作,我們得到的是iccIpb.Stub的內(nèi)部類Proxy對象,而且在這個(gè)類的內(nèi)部擁有IIccPhoneBook.aidl文件定義的接口。 客戶端可以把這個(gè)代理類當(dāng)作服務(wù)端對象一樣去調(diào)用AIDL中定義的所有方法 。
? ? ? ? 下面我們用圖來總結(jié)一下客戶端得到服務(wù)端的過程:
四、客戶端調(diào)用Service方法的過程
? ? ? ? 經(jīng)過3.2節(jié)的分析我們知道,通過IIccPhoneBook.Stub.asInterface()我們得到了一個(gè)服務(wù)端的代理對象:IIccPhoneBook.Stub.Proxy,我們可以直接調(diào)用IIccPhoneBook.aidl中定義的接口,那么這個(gè)代理類如何把接口的調(diào)用傳遞給服務(wù)端呢?服務(wù)器又是如何把數(shù)據(jù)返回給客戶端的呢?? ? ? ? 現(xiàn)在我們先借用IMyService去分析其調(diào)用過程,最后再把過程擴(kuò)大到其他的Java層Service調(diào)用過程中。
? ? ? ? 假如客戶端調(diào)用了IMyService.aidl中的getValue()方法(我們的IMyService.aidl文件中只有這一個(gè)方法),那么就會調(diào)用到Proxy類的內(nèi)部: [java]?view plaincopy
? ? ? ? 還記得在創(chuàng)建Proxy類的時(shí)候我們是把目標(biāo)Service的BpBinder對象傳遞給了mRemote變量,那么這里的transact()就會調(diào)用到BpBinder中: [java]?view plaincopy
? ? ? ? 而根據(jù)《Binder源碼分析之Native層》中的分析,服務(wù)端在接收到客戶端請求后,最終會調(diào)用到服務(wù)端父類BBinder的transact()方法: [java]?view plaincopy
? ? ? ? 那么,當(dāng)客戶端調(diào)用的方法需要返回值時(shí),服務(wù)端是如何把返回值傳回給客戶端的呢?
? ? ? ? 我們還來看getValue()的過程,這個(gè)方法當(dāng)然需要服務(wù)端提供返回值,因此在onTransact()調(diào)用到子類的this.getValue()時(shí),就會得到服務(wù)端的返回值,接下來我們看到,在TRANSACTION_getValue分支中會把返回值(_result)放入reply中,接著就結(jié)束了onTransact()的調(diào)用。
? ? ? ? 也就是說, 在服務(wù)端的onTransact()過程中,不僅完成了對服務(wù)端的調(diào)用,而且也帶回來了服務(wù)端的返回值,這個(gè)返回值是通過onTransact()的參數(shù)傳遞出去的 。
? ? ? ? 然后當(dāng)BBinder的onTransact()結(jié)束后,就返回到了BBinder的transact()操作中,接著再層層返回,并經(jīng)過Native層Binder的傳輸,再次回到BpBinder的transact()中,然后等BpBinder的transact()返回后,我們就再次回到了IMyService.java中的getValue()方法: [java]?view plaincopy
? ? ? ? 如果結(jié)合這IIccPhoneBook來分析,此時(shí)的調(diào)用將會從IIccPhoneBook.Stub中返回到其子類中也就是IccProvider中,從而完成了客戶端的調(diào)用過程。
? ? ? ? 也就是說, 我們在IccProvider對客戶端的調(diào)用經(jīng)過IIccPhoneBook傳遞到Native層,然后又經(jīng)過IccProvider傳遞給Service的實(shí)現(xiàn)者IccPhoneBookInterfaceManagerProxy。完成請求后,再經(jīng)過逆過程回到IccProvider客戶端中 。
? ? ? ? 這就是Java層的Binder調(diào)用過程。
? ? ? ? 最后,用一張圖來示意客戶端調(diào)用服務(wù)端的過程:
原文地址:http://blog.csdn.net/u010961631/article/details/20691793
總結(jié)
以上是生活随笔為你收集整理的Binder源码分析之Java层(原)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Binder源码分析之Native层(原
- 下一篇: Android存储系统之架构篇