文《Android系統的Binder機制之二——服務代理對象(1)》咱們學習了進程的C/C++層面的服務代理對象BpBinder,和Binder底層處理方式。本文咱們將深刻分析一下在進程的Java層面服務代理對象的建立和使用。html
Android中程序大部分都是java開發,底層經過JNI調用C/C++的代碼。這樣一個程序就分爲了兩個層面C/C++層面和Java層面。運行狀態下,咱們說它們都在一個進程之中,擁有相同的進程屬性(UID,GID等等)。java
Binder客戶程序的C/C++層面的對象和原理咱們在上文《Android系統的Binder機制之二——服務代理對象(1)》已經學習。下面咱們將介紹客戶程序怎樣在Java層面經過JNI調用底層C/C++代碼的建立服務代理。android
我在《Android系統的Binder機制之一——Service Manager》中介紹過,客戶端要想得到服務代理,首先要向ServiceManager查詢Service。在Java層面也是這樣,因此咱們首先分析Java層面ServiceManager類。cookie
咱們經過查看ServiceManager的源碼咱們發現,ServiceManager類型也是一個Singleton類型。全部的方法都是靜態方法,全部靜態方法都是訪問它的IServiceManager類型的靜態變量sServiceManager,定義以下:網絡
1: private static IServiceManager sServiceManager;
因此能夠理解ServiceManager就是IServiceManager對象的一個代理。爲建立和訪問這個變量都是經過ServiceManager的getIServiceManager方法,定義以下:app
1: private static IServiceManager getIServiceManager() {
2: if (sServiceManager != null) {
3: return sServiceManager;
4: }
5:
6: // Find the service manager
7: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
8: return sServiceManager;
9: }
經過上面的代碼,很是清晰的告訴咱們ServiceManager類型是一個Singleton類型。如今咱們主要研究sServiceManager對象怎樣建立的。以下代碼建立IServiceManager對象:框架
1: sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
咱們首先查看BinderInternal類的getContextObject方法的代碼,發現是Native代碼(哈哈!有終於到達C/C++層面了,咱們已經熟悉了),對應的代碼爲android_util_binder.cpp中的android_os_BinderInternal_getContextObject函數,代碼以下:函數
1: static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
2: {
3: sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
4: return javaObjectForIBinder(env, b);
5: }
終於看到咱們上文《Android系統的Binder機制之二——服務代理對象(1)》介紹過的ProcessState對象了,咱們再去查看ProcessState對象的getContextObject方法,代碼以下:學習
1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
2: {
3: if (supportsProcesses()) {
4: return getStrongProxyForHandle(0);
5: } else {
6: return getContextObject(String16("default"), caller);
7: }
8: }
咱們看到在當前進程的ProcessState對象實際上是調用getStrongProxyForHandle方法來建立binder句柄爲0的服務代理對象——BpBinder對象,咱們在《Android系統的Binder機制之一——Service Manager》提到過ServiceManager的binder句柄是一個聞名句柄0。上文《Android系統的Binder機制之二——服務代理對象(1)》已經介紹過ProcessState對象的getStrongProxyForHandle方法,這裏就很少說了。this
咱們能夠看出Java調用C/C++,建立一個服務代理對象BpBinder,在查看BpBinder的定義咱們發現繼承自IBinder接口,而後在android_util_binder.cpp中的方法android_os_BinderInternal_getContextObject中,把C/C++層面的IBinder對象封裝成Java層面的IBinder對象。具體實現能夠查看上文的android_os_BinderInternal_getContextObject方法。
至此咱們已經清楚BinderInternal.getContextObject(),返回的是ServiceManager的服務代理對象——BpBinder對象。那麼ServiceManagerNative類的靜態方法asInterface作什麼用呢?咱們仍是經過代碼來分析,在ServiceManagerNative.java中,asInterface的代碼以下:
1: static public IServiceManager asInterface(IBinder obj)
2: {
3: if (obj == null) {
4: return null;
5: }
6: IServiceManager in =
7: (IServiceManager)obj.queryLocalInterface(descriptor);
8: if (in != null) {
9: return in;
10: }
11:
12: return new ServiceManagerProxy(obj);
13: }
將會用IBinder對象建立一個ServiceManagerProxy對象,ServiceManagerProxy類型繼承了IServiceManager接口,因此asInterface方法最終目的是用一個IBinder對象建立一個IServiceManager對象。
爲何要用IBinder對象建立一個IServiceManager對象呢?經過ServiceManager的代理對象——IBinder對象(BpBinder對象)應該能夠直接請求ServiceManager中的服務了啊?咱們在前文《Android系統的Binder機制之二——服務代理對象(1)》簡單介紹了一下IBinder類型,客戶端經過transact方法向Service發送請求,客戶端的onTransact被調用處理客戶端的請求,請求經過請求代碼來區分。具體請參考Android手冊。若是客戶端直接用調用ServiceManager的代理對象的IBinder接口,那麼客戶端必需要記住全部請求的請求代碼,對客戶端來講不太友好。因此在ServiceManagerNative類中就把ServiceManager的代理對象——IBinder對象(BpBinder對象)封裝成ServiceManagerProxy對象,暴露給客戶程序一個IServiceManager接口,這樣IServiceManager對象將會代理客戶程序發往ServiceManager的代理對象的請求。而且是調用IServiceManager對象的方法來給ServiceManager發送請求,這樣對客戶程序來說和本地的函數調用是一致的,接口很是友好。好比咱們客戶程序須要調用IServiceManager的getService方法來查詢一個Service,ServiceManagerProxy實現代碼以下:
1: public IBinder getService(String name) throws RemoteException {
2: Parcel data = Parcel.obtain();
3: Parcel reply = Parcel.obtain();
4: data.writeInterfaceToken(IServiceManager.descriptor);
5: data.writeString(name);
6: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
7: IBinder binder = reply.readStrongBinder();
8: reply.recycle();
9: data.recycle();
10: return binder;
11: }
咱們能夠很是清晰的看到ServiceManagerProxy對象將客戶程序的請求轉換成對ServiceManager代理對象——IBinder對象(BpBinder對象)的調用。後文咱們將會詳細介紹怎樣經過IServiceManager查詢和得到一個系統Service代理對象。
到這裏咱們已經分析完了,ServiceManager的Singleton對象——sServiceManager的建立。若是有不清楚的地方請查看代碼。
客戶程序經過調用ServiceManager類型的靜態方法asInterface得到了IServiceManager對象,可是最終目的通常都是要查詢和得到其餘的Service,通常都是要調用IServiceManager的getService方法,向ServiceManager得到其餘的Service。好比:
1: IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
上面的代碼中就是調用ServiceManager的靜態方法得到網絡管理服務代理對象。咱們順藤摸瓜,看看系統是怎樣生成這個Service代理對象的。這裏只是簡單說明一下調用順序,詳細過程請查看源碼。
一、調用ServiceManager.java中的ServiceManager靜態方法getService。
二、調用ServiceManagerNative.java中的ServiceManagerProxy方法getService。代碼以下:
1: public IBinder getService(String name) throws RemoteException {
2: Parcel data = Parcel.obtain();
3: Parcel reply = Parcel.obtain();
4: data.writeInterfaceToken(IServiceManager.descriptor);
5: data.writeString(name);
6: mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
7: IBinder binder = reply.readStrongBinder();
8: reply.recycle();
9: data.recycle();
10: return binder;
11: }
請注意IBinder的transact方法是同步方法(本例中ServiceManager處理完成請求以後纔會返回),咱們能夠看出調用transact以後,調用reply.readStrongBinder()來讀取IBinder對象。
三、查看Parcel.java中的readStrongBinder方法,發現是Native方法,將會調用到C/C++的代碼。
四、查看android_util_binder.cpp中的android_os_Parcel_readStrongBinder函數。代碼以下:
1: static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
2: {
3: Parcel* parcel = parcelForJavaObject(env, clazz);
4: if (parcel != NULL) {
5: return javaObjectForIBinder(env, parcel->readStrongBinder());
6: }
7: return NULL;
8: }
parcel->readStrongBinder()將會產生一個IBinder對象。
五、查看Parcel.cpp中,Parcel的方法readStrongBinder。代碼以下:
1: sp<IBinder> Parcel::readStrongBinder() const
2: {
3: sp<IBinder> val;
4: unflatten_binder(ProcessState::self(), *this, &val);
5: return val;
6: }
六、查看Parcel.cpp中,Parcel的方法unflatten_binder。代碼以下:
1: status_t unflatten_binder(const sp<ProcessState>& proc,
2: const Parcel& in, sp<IBinder>* out)
3: {
4: const flat_binder_object* flat = in.readObject(false);
5:
6: if (flat) {
7: switch (flat->type) {
8: case BINDER_TYPE_BINDER:
9: *out = static_cast<IBinder*>(flat->cookie);
10: return finish_unflatten_binder(NULL, *flat, in);
11: case BINDER_TYPE_HANDLE:
12: *out = proc->getStrongProxyForHandle(flat->handle);
13: return finish_unflatten_binder(
14: static_cast<BpBinder*>(out->get()), *flat, in);
15: }
16: }
17: return BAD_TYPE;
18: }
終於看到調用咱們的老朋友ProcessState對象的getStrongProxyForHandle方法了,這樣將會建立一個BpBinder對象,而後該BpBinder對象將會被轉換成IBinder對象返回給Java層。
七、Java層爲了用使用Service方便,能夠把Service代理對象——BpBinder對象(IBinder對象)封裝成一個對客戶程序友好的代理對象,就如前面ServiceManagerProxy所示那樣。
八、用戶程序就能夠經過該代理對象訪問相應Service了。
經過所述,咱們瞭解了Service代理對象在Java層的建立和使用。Android系統的Binder機制博大精深,我在本文中不少方面都是走馬觀花,若是想深刻學習請參閱Android的源碼。
參考資料: