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