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

打開APP
userphoto
未登錄

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

開通VIP
Binder機(jī)制,從Java到C (5. IBinder對象傳遞形式)

1.IBinder的傳遞

Binder IPC通信中,Binder是通信的媒介,Parcel是通信的內(nèi)容。遠(yuǎn)程調(diào)用過程中,其參數(shù)都被打包成Parcel的形式來傳遞。IBinder對象當(dāng)然也不例外,在前一篇 Binder機(jī)制,從Java到C (4. Parcel) 中說到IBinder對象是能夠進(jìn)行進(jìn)程間傳遞的。

下面就看一下IBinder對象在傳遞過程中會有什么變化。

在IPC通信的Proxy端,我們經(jīng)??梢钥吹较旅骖愃频拇a,一些參數(shù)都會打包到Parcel中??聪旅娴膁ata和reply。

 1 public void publishService(IBinder token, 2             Intent intent, IBinder service) throws RemoteException { 3         Parcel data = Parcel.obtain(); 4         Parcel reply = Parcel.obtain(); 5         data.writeInterfaceToken(IActivityManager.descriptor); 6         data.writeStrongBinder(token); 7         intent.writeToParcel(data, 0); 8         data.writeStrongBinder(service); 9         mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);10         reply.readException();11         data.recycle();12         reply.recycle();13     }

在IPC通信里,android是通過Parcel類的成員函數(shù)writeStrongBinder()向Parcel寫入IBinder,再通過mRemote發(fā)送出去。

 

2.writeStrongBinder()

接下來就看一下writeStrongBinder()這個函數(shù)里做了什么。
/frameworks/base/core/java/android/os/Parcel.java

 1 public final class Parcel { 2  3     /** 4      * Write an object into the parcel at the current dataPosition(), 5      * growing dataCapacity() if needed. 6      */ 7     public final void writeStrongBinder(IBinder val) { 8         nativeWriteStrongBinder(mNativePtr, val); 9     }10     private static native void nativeWriteStrongBinder(int nativePtr, IBinder val);11 12 }

 

看,這里又調(diào)用了native方法,我們會發(fā)現(xiàn)Java 層的一些Parcel其實只是對C/C++層的一個封裝,大部分操作還是依靠JNI去調(diào)用Native的操作。
那看一下C++里對應(yīng)的方法:

/frameworks/base/core/jni/android_os_Parcel.cpp

 1 static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr, jobject object) 2 { 3     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 4     if (parcel != NULL) { 5         const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 6         if (err != NO_ERROR) { 7             signalExceptionForError(env, clazz, err); 8         } 9     }10 }

最主要的就是ibinderForJavaObject 這個函數(shù),繼續(xù)跟蹤代碼:

/frameworks/base/core/jni/android_util_Binder.cpp

 1 sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) 2 { 3     if (obj == NULL) return NULL; 4  5     if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { //mClass指向Java層中的Binder class 6         JavaBBinderHolder* jbh = (JavaBBinderHolder*) 7             env->GetIntField(obj, gBinderOffsets.mObject); 8         return jbh != NULL ? jbh->get(env, obj) : NULL; //get() 返回一個JavaBBinder,繼承自BBinder 9     }10 11     if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { //mClass 指向Java層的BinderProxy class12         return (IBinder*)13             env->GetIntField(obj, gBinderProxyOffsets.mObject); //返回一個BpBinder,mObject是它的地址值14     }15     ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);16     return NULL;17 }

這個函數(shù)呢,就是根據(jù)傳進(jìn)來的Java對象找到對應(yīng)的C++對象,這里的參數(shù)obj,可能會指向兩種對象:Binder對象或者BinderProxy對象。這兩個對象我們在RemoteService那一篇里其實就遇到過了,Binder對象呢就是Service里實現(xiàn)的那個mRemoteBinder,BinderProxy對象呢就是Activity里回調(diào)傳進(jìn)來的那個service。不記得的話,可以再看一下那一篇:Binder機(jī)制,從Java到C (1. IPC in Application Remote Service)

接著說,如果傳進(jìn)來的是Binder對象,那么就會把gBinderOffsets.mObject轉(zhuǎn)化成JavaBBinderHolder, 并從中獲得一個JavaBBinder對象。JavaBBinder繼承自BBinder。(在RemoteService那一篇,Service會在onBind回調(diào)里把mRemoteBinder傳給AMS,這里傳遞的就是Binder對象)

如果傳進(jìn)來的是BinderProxy對象。就會返回一個BpBinder,這個BpBinder的地址值就保存在gBinderProxyOffsets.mObject中。(在RemoteService那一篇,AMS要傳遞給Acticity的就是BinderProxy對象)。

到這里,你可能會奇怪,為什么Service把Binder對象傳遞給AMS,后面AMS卻是把BinderProxy對象傳遞給Activity呢?這個我們后面再說,(可以先說一下,其實是因為這些Binder對象都會經(jīng)過底層傳輸,那在傳輸?shù)倪^程中,Binder模塊就會根據(jù)不同的情況對這些對象進(jìn)行轉(zhuǎn)化)

好吧,那還是接著說,有發(fā)送,當(dāng)然會有接收,再來看一下Parcel的readStrongBinder():


3.readStrongBinder()

同樣也是JNI調(diào)用:

/frameworks/base/core/jni/android_os_Parcel.cpp

 1 static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr) 2 { 3       ... 4       return javaObjectForIBinder(env, parcel->readStrongBinder()); 5 } 6  7 /frameworks/base/core/jni/android_util_Binder.cpp 8 jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) (1) 9 {10     if (val == NULL) return NULL;11     if (val->checkSubclass(&gBinderOffsets)) { (2)12         // One of our own!13         jobject object = static_cast<JavaBBinder*>(val.get())->object();14         LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);15         return object;16     }17    ...18     jobject object = (jobject)val->findObject(&gBinderProxyOffsets);19     if (object != NULL) {20         jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet); (3)21         if (res != NULL) {22             ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);23             return res;24         }25        ...26     }27     object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); (4)28     if (object != NULL) {29        ….30     }31     return object;32 }

 

(1):這里的val和writeStrongBinder類似,不過是反過來,指向的可能是JavaBBinder或者BpBinder。

(2)如果是JavaBBinder,就會通過成員函數(shù)object(),返回一個Java對象,這個對象就是Java層的Binder對象。

(3)如果是BpBinder,那就先查找是否已經(jīng)存在需要使用的BinderProxy對象,如果找到就返回引用

(4)如果沒找到可用的引用,就new 一個BinderProxy對象。

 

4.Binder Module in Kernel

實際上,在Client端將參數(shù)打包成Parcel后,會發(fā)送到kernel的Binder module。在Binder module中,會有兩種IBinder類型:BINDER_TYPE_BINDER,BINDER_TYPE_HANDLE。也對應(yīng)著ava的本地對象和代理對象。

在Binder module收到數(shù)據(jù)后,會對不同的情況做進(jìn)一步處理:
1.傳來的IBinder類型是BINDER_TYPE_BINDER, 會將binder_type轉(zhuǎn)化為BINDER_TYPE_HANDLE;

(這里理解起來有點別扭,因為只有在不同進(jìn)程間傳遞IBinder時,才會把IBinder傳遞到kernel里,所以傳遞進(jìn)來的IBinder必定是傳遞給別的process,不會是IBinder所在的process,這時,IBinder所在的process和發(fā)送目標(biāo)process不是同一個,就需要改成BINDER_TYPE_HANDLE。如果IBinder是在同一個進(jìn)程間傳遞,也不會進(jìn)入到kernel里。所以一個BINDER_TYPE_BINDER類型的IBinder傳進(jìn)kernel,就必然需要轉(zhuǎn)化成BINDER_TYPE_HANDLE)

2.傳來的IBinder類型是BINDER_TYPE_HANDLE,會判斷這個IBinder實體定義的process和發(fā)送的目標(biāo)process是否相同,如果相同,就將binder_type轉(zhuǎn)化成BINDER_TYPE_BINDER。如果不同,保持BINDER_TYPE_HANDLE。

因為只有不同進(jìn)程間傳遞才會把IBinder發(fā)送到Binder module,所以在IBinder的傳遞中,可能會有2中可能。
1.process A → process B → process A
2.process A → process B → process C

這時候,對應(yīng)的IBinder類型就會是:
1.BINDER_TYPE_BINDER → BINDER_TYPE_HANDLE → BINDER_TYPE_BINDER
2.BINDER_TYPE_BINDER → BINDER_TYPE_HANDLE → BINDER_TYPE_HANDLE

 

 

 

 

5.再看 Bind service

實際上,bind一個service的過程,也就是上述的第2中情況。

 

 

 

 

 

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android 開發(fā)之漫漫長途 IX——徹底掌握 Binder
Binder基本概念流程學(xué)習(xí)
Android深入淺出之Binder機(jī)制 - innost - 博客園
分析獲取當(dāng)前系統(tǒng)進(jìn)程列表的代碼流程(及ioctl在bionic庫中的實現(xiàn))
AIDL的接觸和使用
Android 內(nèi)核--Binder架構(gòu)分析
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服