久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Binder機制,,從Java到C (5. IBinder對象傳遞形式)

 just_person 2014-11-14

1.IBinder的傳遞

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

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

在IPC通信的Proxy端,我們經??梢钥吹较旅骖愃频拇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 }
復制代碼

 

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

/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 class
12         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ù)傳進來的Java對象找到對應的C++對象,這里的參數(shù)obj,可能會指向兩種對象:Binder對象或者BinderProxy對象,。這兩個對象我們在RemoteService那一篇里其實就遇到過了,,Binder對象呢就是Service里實現(xiàn)的那個mRemoteBinder,BinderProxy對象呢就是Activity里回調傳進來的那個service。不記得的話,,可以再看一下那一篇:Binder機制,,從Java到C (1. IPC in Application Remote Service)

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

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

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

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


3.readStrongBinder()

同樣也是JNI調用:

/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,那就先查找是否已經存在需要使用的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,。也對應著ava的本地對象和代理對象,。

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

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

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

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

這時候,對應的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ǎng)絡存儲空間,,所有內容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多