国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Binder源碼分析之Java層(原)
        前面的幾節(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類的代碼:
  1. @ServiceManager.java(google-code\frameworks\base\core\java\android\os\ServiceManager.java)  
  2. public final class ServiceManager {  
  3.     private static IServiceManager getIServiceManager() {  
  4.     }  
  5.     public static IBinder getService(String name) {  
  6.     }  
  7.     public static void addService(String name, IBinder service) {  
  8.     }  
  9.     public static void addService(String name, IBinder service, boolean allowIsolated) {  
  10.     }  
  11.     public static IBinder checkService(String name) {  
  12.     }  
  13.     public static String[] listServices() throws RemoteException {  
  14.     }  
  15.     public static void initServiceCache(Map<String, IBinder> cache) {  
  16.     }  
  17. }  

        這個類比較簡單,而且我們看到,ServiceManager沒有繼承任何的類,那么他是如何實現(xiàn)“管理員”的角色呢?


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

        Android啟動時,將會在SystemServer中的ServerThread線程中將一些重要的Java層Service注冊并啟動,我們在這里挑選負責狀態(tài)欄管理的StatusBarManagerService來分析。
  1. @SystemServer.java(google-code\frameworks\base\services\java\com\android\server\SystemServer.java)  
  2. class ServerThread extends Thread {  
  3.     @Override  
  4.     public void run() {  
  5.         try {  
  6.             statusBar = new StatusBarManagerService(context, wm);  
  7.             //調(diào)用ServiceManager注冊服務  
  8.             ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);  
  9.         } catch (Throwable e) {  
  10.             reportWtf("starting StatusBarManagerService", e);  
  11.         }  
  12.     }  
  13. }  
        我們看到,作為一個Service,可以通過調(diào)用ServiceManager的addService()方法注冊自己。注冊的時候傳遞了兩個參數(shù),Context.STATUS_BAR_SERVICE作為該Service的name,StatusBarManagerService作為該Service的BBinder子類對象,一起傳遞給了ServiceManager。這樣的形式正符合Native層ServiceManager中Service的注冊方式。
        我們來看ServiceManager的addService()方法:
  1. @ServiceManager.java  
  2. public static void addService(String name, IBinder service) {  
  3.     try {  
  4.         getIServiceManager().addService(name, service, false);  
  5.     } catch (RemoteException e) {  
  6.         Log.e(TAG, "error in addService", e);  
  7.     }  
  8. }  
        在addService()內(nèi)部,把addService()的請求轉(zhuǎn)發(fā)給了getIServiceManager()得到的對象。
  1. private static IServiceManager sServiceManager;  
  2. private static IServiceManager getIServiceManager() {  
  3.     if (sServiceManager != null) {  
  4.         //單例模式  
  5.         return sServiceManager;  
  6.     }  
  7.     //得到ServiceManager的Java層代理對象  
  8.     sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
  9.     return sServiceManager;  
  10. }  
        這里看到,通過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()對象,下面我們來看這個方法的聲明:
  1. @BinderInternal.java(google-code\frameworks\base\core\java\com\android\internal\os\BinderInternal.java)  
  2. public static final native IBinder getContextObject();  
        他的聲明方式說明這個方法是在Native中被實現(xiàn)的,那么他具體定義是在哪里呢?
        我們簡單來說一下流程。
        在Java虛擬機啟動時,將會注冊一系列的native方法
  1. @AndroidRuntime.cpp(google-code\frameworks\base\core\jni\AndroidRuntime.cpp)  
  2. void AndroidRuntime::start(const char* className, const char* options) {  
  3.     //開始注冊方法  
  4.     if (startReg(env) < 0) {  
  5.         return;  
  6.     }  
  7. }  
        在虛擬機啟動時,將會通過startReg()方法去注冊jni:
  1. int AndroidRuntime::startReg(JNIEnv* env) {  
  2.     //注冊gRegJNI列表中的jni方法  
  3.     if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {  
  4.         env->PopLocalFrame(NULL);  
  5.         return -1;  
  6.     }  
  7.     return 0;  
  8. }  
        在上面的startReg()中將會遍歷gRegJNI列表并注冊,我們來看需要注冊的列表內(nèi)容:
  1. static const RegJNIRec gRegJNI[] = {  
  2.     REG_JNI(register_android_os_Binder),  
  3. };  
        其中就包括了register_android_os_Binder():
  1. @android_util_Binder.cpp(google-code\frameworks\base\core\jni\android_util_Binder.cpp)  
  2. int register_android_os_Binder(JNIEnv* env) {  
  3.     //注冊BinderInternal中的jni  
  4.     if (int_register_android_os_BinderInternal(env) < 0)  
  5.         return -1;  
  6.     return 0;  
  7. }  
        在register_android_os_Binder中對BinderInternal中的jni進行注冊:
  1. static int int_register_android_os_BinderInternal(JNIEnv* env) {  
  2.     jclass clazz;  
  3.     //根據(jù)路徑找到類  
  4.     clazz = env->FindClass(kBinderInternalPathName);  
  5.     gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  6.     gBinderInternalOffsets.mForceGc = env->GetStaticMethodID(clazz, "forceBinderGc""()V");  
  7.   
  8.     //注冊gBinderInternalMethods中的jni  
  9.     return AndroidRuntime::registerNativeMethods(  
  10.             env, kBinderInternalPathName,  
  11.             gBinderInternalMethods, NELEM(gBinderInternalMethods));  
  12. }  
        我們再來看gBinderInternalMethods中定義的方法:
  1. static const JNINativeMethod gBinderInternalMethods[] = {  
  2.     { "getContextObject""()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },  
  3.     { "joinThreadPool""()V", (void*)android_os_BinderInternal_joinThreadPool },  
  4.     { "disableBackgroundScheduling""(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },  
  5.     { "handleGc""()V", (void*)android_os_BinderInternal_handleGc }  
  6. };  
        這個數(shù)組中就定義了getContextObject方法所對應的jni實現(xiàn),其實就是android_os_BinderInternal_getContextObject(),也就是說,getContextObject()將會調(diào)用到android_os_BinderInternal_getContextObject(),我們看一下這個方法的定義:
  1. static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) {  
  2.     //得到BpBinder(0)對象  
  3.     sp<IBinder> b = ProcessState::self()->getContextObject(NULL);  
  4.     //將BpBinder對象轉(zhuǎn)換為Java對象  
  5.     return javaObjectForIBinder(env, b);  
  6. }  
        在這個方法中,完成了兩步重要的操作:
        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()方法完成注冊:
  1. private static IServiceManager getIServiceManager() {  
  2.     if (sServiceManager != null) {  
  3.         //單例模式  
  4.         return sServiceManager;  
  5.     }  
  6.     //得到ServiceManager的Java層代理對象  
  7.     sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
  8.     return sServiceManager;  
  9. }  
        經(jīng)過前面2.1的分析,我們了解了通過BinderInternal.getContextObject()可以得到BpBinder(0)的Java層代理對象,接下來就需要調(diào)用ServiceManagerNative的asInterface()方法將該對象轉(zhuǎn)換為Java層可用的ServiceManager代理對象。
        也就是說,當前的getIServiceManager()相當于:
  1. private static IServiceManager getIServiceManager() {  
  2.     //得到ServiceManager的Java層代理對象  
  3.     sServiceManager = ServiceManagerNative.asInterface(BpBinder(0));  
  4.     return sServiceManager;  
  5. }  
        我們接下來看ServiceManagerNative的asInterface()的過程。
  1. @ServiceManagerNative.java(google-code\frameworks\base\core\java\android\os\ServiceManagerNative.java)  
  2. static public IServiceManager asInterface(IBinder obj)  
  3. {  
  4.     if (obj == null) {  
  5.         return null;  
  6.     }  
  7.     //查詢本地緩存  
  8.     IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);  
  9.     if (in != null) {  
  10.         return in;  
  11.     }  
  12.     //創(chuàng)建代理對象  
  13.     return new ServiceManagerProxy(obj);  
  14. }  
        我們看到,通過asInterface()的轉(zhuǎn)換,我們用BpBinder對象生成了ServiceManagerProxy對象
        也就是說,通過getIServiceManager()得到的sServiceManager對象,其實是ServiceManagerProxy對象。

2.3、ServiceManagerProxy對象

        我們先來看一下其繼承結(jié)構(gòu):
  1. class ServiceManagerProxy implements IServiceManager {}  
        從繼承關(guān)系上來看,ServiceManagerProxy實現(xiàn)了IServiceManager中定義的接口。
        然后再來看其構(gòu)造函數(shù),在2.2中介紹過,創(chuàng)建ServiceManagerProxy對象時,是用ServiceManager的BpBinder對象作為參數(shù)的:
  1. public ServiceManagerProxy(IBinder remote) {  
  2.     mRemote = remote;  
  3. }  
        這里的構(gòu)造函數(shù)中,把BpBinder(0)保存在了mRemote變量中。
        下面我們來看ServiceManagerProxy中的方法:
  1. class ServiceManagerProxy implements IServiceManager {  
  2.     public ServiceManagerProxy(IBinder remote) {  
  3.     }  
  4.   
  5.     public IBinder asBinder() {  
  6.     }  
  7.   
  8.     public IBinder getService(String name) throws RemoteException {  
  9.     }  
  10.   
  11.     public IBinder checkService(String name) throws RemoteException {  
  12.     }  
  13.   
  14.     public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {  
  15.     }  
  16.   
  17.     public String[] listServices() throws RemoteException {  
  18.     }  
  19.   
  20.     public void setPermissionController(IPermissionController controller) throws RemoteException {  
  21.     }  
  22. }  
        我們看到,ServiceManagerProxy確實實現(xiàn)了IServiceManager中的方法,提供了add、get、check、list等功能。

2.4、注冊Service的過程

        經(jīng)過以上的分析,我們知道通過getIServiceManager()的調(diào)用,我們得到的是ServiceManagerProxy對象,那么當注冊Service時調(diào)用的addService()方法就會調(diào)用到ServiceManagerProxy中:
  1. public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {  
  2.     Parcel data = Parcel.obtain();  
  3.     Parcel reply = Parcel.obtain();  
  4.     data.writeInterfaceToken(IServiceManager.descriptor);  
  5.     data.writeString(name);  
  6.     data.writeStrongBinder(service);  
  7.     data.writeInt(allowIsolated ? 1 : 0);  
  8.     mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);  
  9.     reply.recycle();  
  10.     data.recycle();  
  11. }  
        在addService的時候,將當前Service的name和service對象封裝到Parcel類型的data中,然后調(diào)用mRemote對象的transact()方法發(fā)送出去,并標記當前的操作是“ADD_SERVICE_TRANSACTION”,還記得我們在分析ServiceManagerProxy的構(gòu)造函數(shù)時傳遞的參數(shù)其實是BpBinder對象,那么這里的transact()就會調(diào)用到BpBinder中:
  1. @BpBinder.cpp  
  2. status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     if (mAlive) {  
  4.         //進入IPCThreadState繼續(xù)調(diào)用  
  5.         status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags);  
  6.         if (status == DEAD_OBJECT) mAlive = 0;  
  7.         return status;  
  8.     }  
  9.     return DEAD_OBJECT;  
  10. }  
        到這里,就進入了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的過程:
  1. @IccPhoneBookInterfaceManagerProxy.java(google-code\frameworks\opt\telephony\src\java\com\android\Internal\telephony\)  
  2. public IccPhoneBookInterfaceManagerProxy(IccPhoneBookInterfaceManager iccPhoneBookInterfaceManager) {  
  3.     mIccPhoneBookInterfaceManager = iccPhoneBookInterfaceManager;  
  4.     if(ServiceManager.getService("simphonebook") == null) {  
  5.         ServiceManager.addService("simphonebook"this);  
  6.     }  
  7. }  
        這就是simphonebook的注冊過程,看似簡單,但是有個疑問,我們知道,在addService()的操作時,必須傳遞2個參數(shù):name+IBinder子類對象,但是這里的this所指的IccPhoneBookInterfaceManagerProxy對象,是IBinder子類的對象嗎?
        我們來看IccPhoneBookInterfaceManagerProxy這個類的繼承關(guān)系:
  1. 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)容為:
  1. @IMyService.aidl  
  2. package com.pack;  
  3. interface IMyService{  
  4.     String getValue();  
  5. }  
        這個文件中只有一個方法getValue(),然后我們來看系統(tǒng)為其生成的Java文件:
  1. @IMyService.java  
  2. package com.pack;  
  3. public interface IMyService extends android.os.IInterface {  
  4.     //Stub繼承自Binder,并且實現(xiàn)了IMyService的接口  
  5.     public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {  
  6.     }  
  7. }  
        從生成的Java文件可以看出,IMyService.Stub是android.os.Binder的子類,而android.os.Binder又是IBinder的子類:
  1. @Binder.java(google-code\frameworks\base\core\java\android\os\)  
  2. public class Binder implements IBinder{}  
        由此我們推斷,IccPhoneBookInterfaceManagerProxy的父類IIccPhoneBook.Stub也是IBinder的子類。下面我們來看這個Service的使用方法。
  1. @IccProvider.java(google-code\frameworks\opt\telephony\src\java\com\android\internal\telephony\)  
  2. private boolean addIccRecordToEf(int efType, String name, String number, String[] emails, String pin2) {  
  3.     boolean success = false;  
  4.     try {  
  5.         //得到simphonebook的Service  
  6.         IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));  
  7.         if (iccIpb != null) {  
  8.             //添加SIM卡聯(lián)系人  
  9.             success = iccIpb.updateAdnRecordsInEfBySearch(efType, """", name, number, pin2);  
  10.         }  
  11.     } catch (RemoteException ex) {  
  12.     } catch (SecurityException ex) {  
  13.     }  
  14.     return success;  
  15. }  
        上面這個方法的作用就是向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()方法:
  1. @ServiceManager.java  
  2. public static IBinder getService(String name) {  
  3.     try {  
  4.         IBinder service = sCache.get(name);  
  5.         if (service != null) {  
  6.             return service;  
  7.         } else {  
  8.             //調(diào)用的是getIServiceManager()對象的getService()方法  
  9.             return getIServiceManager().getService(name);  
  10.         }  
  11.     } catch (RemoteException e) {  
  12.     }  
  13.     return null;  
  14. }  
  15. private static IServiceManager getIServiceManager() {  
  16.     if (sServiceManager != null) {  
  17.         return sServiceManager;  
  18.     }  
  19.     //通過getIServiceManager得到的其實是ServiceManager的Java層代理對象  
  20.     sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  
  21.     return sServiceManager;  
  22. }  
        在2.2節(jié)中我們介紹過,在getIServiceManager()中得到的對象,就是ServiceManager在Java層的代理對象:ServiceManagerProxy。
        那么調(diào)用該代理對象的getService()方法將會得到什么呢?
  1. @ServiceManagerNative.java  
  2. class ServiceManagerProxy implements IServiceManager {  
  3.     //ServiceManagerProxy的getService()方法  
  4.     public IBinder getService(String name) throws RemoteException {  
  5.         Parcel data = Parcel.obtain();  
  6.         Parcel reply = Parcel.obtain();  
  7.         data.writeInterfaceToken(IServiceManager.descriptor);  
  8.         data.writeString(name);  
  9.         //這里的mRemote就是ServiceManager的BpBinder對象  
  10.         mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);  
  11.         IBinder binder = reply.readStrongBinder();  
  12.         reply.recycle();  
  13.         data.recycle();  
  14.         return binder;  
  15.     }  
  16. }  
        我們看到,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層可用的代理對象。
        我們先將代碼簡化一下:
  1. IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));  
        上面的代碼相當于:
  1. IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(BpBinder("simphonebook"));  
        接下來的分析,我們就要繼續(xù)看生成的IIccPhoneBook.java文件了,我們還是借助剛剛生成的IMyService.java文件來看其asInterface()接口:
  1. @IMyService.java  
  2. public interface IMyService extends android.os.IInterface {  
  3.     public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {  
  4.   
  5.         public static com.pack.IMyService asInterface(android.os.IBinder obj) {  
  6.             if ((obj == null)) {  
  7.                 return null;  
  8.             }  
  9.             android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);  
  10.             if (((iin != null) && (iin instanceof com.pack.IMyService))) {  
  11.                 return ((com.pack.IMyService) iin);  
  12.             }  
  13.             //通過asInterface()得到的是Proxy對象,并且把BpBinder對象作為參數(shù)傳遞進去  
  14.             return new com.pack.IMyService.Stub.Proxy(obj);  
  15.         }  
  16.   
  17.         //代理類Proxy繼承自IMyService.aidl,需要實現(xiàn)里面的所有接口  
  18.         private static class Proxy implements com.pack.IMyService {  
  19.             private android.os.IBinder mRemote;  
  20.             //保存得到的BpBinder對象  
  21.             Proxy(android.os.IBinder remote) {  
  22.                 mRemote = remote;  
  23.             }  
  24.   
  25.             @Override  
  26.             public java.lang.String getValue() throws android.os.RemoteException {  
  27.             }  
  28.         }  
  29.   
  30.         static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);  
  31.     }  
  32.     public java.lang.String getValue() throws android.os.RemoteException;  
  33. }  
        原來,我們通過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)部:
  1. private static class Proxy implements com.pack.IMyService {  
  2.     private android.os.IBinder mRemote;  
  3.   
  4.     Proxy(android.os.IBinder remote) {  
  5.         mRemote = remote;  
  6.     }  
  7.   
  8.     @Override  
  9.     public java.lang.String getValue() throws android.os.RemoteException {  
  10.         //準備Parcel數(shù)據(jù)  
  11.         android.os.Parcel _data = android.os.Parcel.obtain();  
  12.         android.os.Parcel _reply = android.os.Parcel.obtain();  
  13.         java.lang.String _result;  
  14.         try {  
  15.             _data.writeInterfaceToken(DESCRIPTOR);  
  16.             //調(diào)用mRemote的transact()方法發(fā)送數(shù)據(jù),并且標記當前調(diào)用的方法為getValue  
  17.             mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply, 0);  
  18.             //提取服務端的返回值  
  19.             _reply.readException();  
  20.             _result = _reply.readString();  
  21.         } finally {  
  22.             _reply.recycle();  
  23.             _data.recycle();  
  24.         }  
  25.         return _result;  
  26.     }  
  27. }  
        在Proxy的getValue()方法中,將客戶端的請求封裝為Parcel類型的數(shù)據(jù)通過mRemote變量發(fā)送出去,而且在發(fā)送時標記了當前的命令是TRANSACTION_getValue,也就是調(diào)用getValue方法,那么這里的mRemote對象是什么呢?
        還記得在創(chuàng)建Proxy類的時候我們是把目標Service的BpBinder對象傳遞給了mRemote變量,那么這里的transact()就會調(diào)用到BpBinder中:
  1. @BpBinder.cpp  
  2. status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     if (mAlive) {  
  4.         //向Service發(fā)送請求  
  5.         status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags);  
  6.         if (status == DEAD_OBJECT) mAlive = 0;  
  7.         return status;  
  8.     }  
  9.     return DEAD_OBJECT;  
  10. }  
        接下來就是Native層的流程了??磥鞵roxy代理的作用就是在客戶端調(diào)用各種方法時,將方法編號(TRANSACTION_getValue)后通過目標Service的BpBinder對象向Native層的Binder機制發(fā)送(transact)請求,同時準備在reply中接收服務端的返回值。
        而根據(jù)《Binder源碼分析之Native層》中的分析,服務端在接收到客戶端請求后,最終會調(diào)用到服務端父類BBinder的transact()方法:
  1. @Binder.cpp  
  2. status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {  
  3.     status_t err = NO_ERROR;  
  4.     switch (code) {  
  5.         case PING_TRANSACTION:  
  6.             reply->writeInt32(pingBinder());  
  7.             break;  
  8.         default:  
  9.             //調(diào)用BBinder的子類去處理當前請求  
  10.             err = onTransact(code, data, reply, flags);  
  11.             break;  
  12.     }  
  13.     return err;  
  14. }  
        我們看到,在BBinder的transact()方法中,將會調(diào)用Service的onTransact()的方法,由于當前的IMyService就是BBinder的子類,因此這里的onTransact()方法將會進入到IMyService的內(nèi)部,也就是:
  1. public interface IMyService extends android.os.IInterface {  
  2.     public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {  
  3.         public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {  
  4.             switch (code) {  
  5.                 case INTERFACE_TRANSACTION: {  
  6.                     reply.writeString(DESCRIPTOR);  
  7.                     return true;  
  8.                 }  
  9.                 case TRANSACTION_getValue: {  
  10.                     //客戶端發(fā)起的getValue()的請求  
  11.                     data.enforceInterface(DESCRIPTOR);  
  12.                     //繼續(xù)調(diào)用子類的getValue()方法  
  13.                     java.lang.String _result = this.getValue();  
  14.                     reply.writeNoException();  
  15.                     reply.writeString(_result);  
  16.                     return true;  
  17.                 }  
  18.             }  
  19.             return super.onTransact(code, data, reply, flags);  
  20.         }  
  21.         static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);  
  22.     }  
  23.     public java.lang.String getValue() throws android.os.RemoteException;  
  24. }  
        我們看到在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()方法:
  1. public java.lang.String getValue() throws android.os.RemoteException {  
  2.     android.os.Parcel _data = android.os.Parcel.obtain();  
  3.     android.os.Parcel _reply = android.os.Parcel.obtain();  
  4.     java.lang.String _result;  
  5.     try {  
  6.         _data.writeInterfaceToken(DESCRIPTOR);  
  7.         //經(jīng)歷了一次漫長的跨進程調(diào)用過程  
  8.         mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply, 0);  
  9.         _reply.readException();  
  10.         _result = _reply.readString();  
  11.     } finally {  
  12.         _reply.recycle();  
  13.         _data.recycle();  
  14.     }  
  15.     return _result;  
  16. }  
        此時的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)用服務端的過程:



本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android 內(nèi)核--Binder架構(gòu)分析
Android 核心分析 之六 -----IPC框架分析 Binder,Service,Service manager
Binder基本概念流程學習
Android深入淺出之Binder機制 - innost - 博客園
Android 之 Binder與進程間通信
騰訊面試官: 說說Binder中系統(tǒng)服務的注冊過程
更多類似文章 >>
生活服務
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服