在具體講解Binder調用流程之前,有必要先把調用流程中和數據相關的類介紹下,通過前面兩節介紹,我們知道Binder對象分爲本地和遠程,在遠程調用進行數據系列化時對這兩種對象處理也是有區別的,下面是Binder調用流程中和數據直接相關的類。
JAVA端
BinderProxy:遠程服務在本地的代理;
Binder:實現IBinder接口,實體Service具體實現一般繼承這個類,表示具體業務邏輯實現;
Parcel:android的數據系列化類,直接在內存中操作,在JAVA端其只是個容器,真正實現在本地端;
對應本地端
BpBinder:遠程服務代理對象,每個服務都會經過Binder驅動生成對應的handle一一對應;
BBinder:據圖服務的實現,其功能之一返回本地IBinder對象,這個對象相關信息會直接傳給Binder驅動;
Parcel:android數據系列化和反系列化本地管理類;
在分析這些類之前,我們先看下本地IBinder對本地對象和遠程對象的接口支持的定義。
frameworks/native/include/binder/IBinder.h
50class IBinder : public virtual RefBase
......
161 virtual BBinder* localBinder(); // (1)
162 virtual BpBinder* remoteBinder(); // (2)
163
164protected:
165 virtual ~IBinder();
166
167private:
168};
(1)返回的是一個本地IBinder對象,什麼叫本地對象?就是調用的進程就是實現這個IBinder的宿主進程,IBinder實體類就存儲在此進程中。
(2)返回的是一個遠程代理對象,就是調用進程和IBinder實體不在同一個進程,其和遠程IBinder實體對象是通過對象的handle進行關聯的。
下面一一分析這些類的具體實現細節,這裏我們只會講和Binder調用流程相關,其它讀者自行查看源碼。
BinderProxy
查看BinderProxy的源碼:
733final class BinderProxy implements IBinder {
......
744 public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
.....
763 try {
764 return transactNative(code, data, reply, flags);
765 } finally {
766 if (tracingEnabled) {
767 Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
768 }
769 }
770 }
上面我們只留下關鍵代碼,首先BinderProxy是從IBinder繼承過來,所有其具有Binder通行的基礎,在其具體實現方法transact裏,我們發現其實際調用的是transactNative方法,這是一個本地方法,定義如下:
public native boolean transactNative(int code, Parcel data, Parcel reply,int flags) throws RemoteException;
這是一個JNI方法,其實現在如下文件中:
frameworks/base/core/jni/android_util_Binder.cpp
在這個文件我們發現定義了BinderProxy的本地方法映射:
static const JNINativeMethod gBinderProxyMethods[] = {
1305 /* name, signature, funcPtr */
1306 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
1307 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
1308 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
1309 {"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
1310 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
1311 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
1312 {"destroy", "()V", (void*)android_os_BinderProxy_destroy},
1313};
transactNative方法在本地對應的實現是android_os_BinderProxy_transact,下面看看這個方法具體做了些什麼:
1141static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
1142 jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
1143{
......
1149 Parcel* data = parcelForJavaObject(env, dataObj); // (1)
......
1153 Parcel* reply = parcelForJavaObject(env, replyObj); // (2)
......
1158 IBinder* target = (IBinder*)
1159 env->GetLongField(obj, gBinderProxyOffsets.mObject); // (3)
......
1182 status_t err = target->transact(code, *data, reply, flags);
1183 ......
1198 return JNI_FALSE;
1199}
其中(1)和(2)後面講Parcel會說,我們來看看(3),這裏從BinderProxy直接取出其成員變量mObject的值,它就是一個本地IBinder類型的對象,那麼這個本地對象是怎麼設置給JAVA層的BinderProxy的呢?從這裏我們可以大致推斷這個JAVA層的BinderProxy對象有可能是在native層創建的。
從上面代碼發現這裏有個結構gBinderProxyOffsets,其定義如下:
96static struct binderproxy_offsets_t
97{
98 // Class state.
99 jclass mClass;
100 jmethodID mConstructor;
101 jmethodID mSendDeathNotice;
102
103 // Object state.
104 jfieldID mObject;
105 jfieldID mSelf;
106 jfieldID mOrgue;
107
108} gBinderProxyOffsets;
這個結構其實就是保持了JAVA層BinderProxy類成員變量和成員方法的相關信息,其中的mObject保存了本地對象,我們看看這個mObject在那裏設置進來的,搜索SetLongField(爲什麼要搜索這個方法?)方法,發現和mObject相關代碼如下:
5jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
596{
......
624 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
625 if (object != NULL) {
......
628 env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
629 val->incStrong((void*)javaObjectForIBinder);
630
在方法中javaObjectForIBinder創建了BinderProxy對象,並把參數val設置給了BinderProxy的mObject成員變量,繼續找javaObjectForIBinder在那裏調用:
950static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
951{
952 sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
953 return javaObjectForIBinder(env, b);
954}
這裏有一處調用,原來這個IBinder是ProcessState::self()->getContextObject(NULL);創建的,看下這個方法就知道了:
238sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
239{
......
244 handle_entry* e = lookupHandleLocked(handle);
245
246 if (e != NULL) {
......
279 b = new BpBinder(handle);
280 e->binder = b;
......
292 return result;
293}
經過層層調用發現,最終會調getStrongProxyForHandle這個方法,原來返回的IBinder是由b = new BpBinder(handle);這句代碼創建的,到這裏我們知道了設置給BinderProxy的mObject成員變量的native對象就是BpBinder,這就對應上了。細心的讀者可能發現,這裏是對本地的BpBinder做了緩存處理的,通過handle來保存。另外,大家也要注意此方法也在Parcel被調用,可見它是獲取遠程服務的本地代理的方法入口。
接着我們看看本地實際的遠程代理對象的實現。
frameworks/native/libs/binder/BpBinder.cpp
307BpBinder* BpBinder::remoteBinder()
308{
309 return this;
310}
看到了吧,其遠程接口 remoteBinder()直接返回BpBinder對象本身,而其本地接口返回的是NULL(IBinder中實現)。
講完了BinderProxy,接下來看下Binder和本地的BBinder又是怎麼回事?
Binder
Binder定義如下:
70public class Binder implements IBinder {
其構造方法如下:
363 public Binder() {
364 init();
......
374 }
其構造方法裏調用了init,init方法是個本地方法,其定義如下:
678 private native final void init();
和上面一樣,在native找到其對應的實現,其定義在如下文件中:
frameworks/base/core/jni/android_util_Binder.cpp
856static void android_os_Binder_init(JNIEnv* env, jobject obj)
857{
858 JavaBBinderHolder* jbh = new JavaBBinderHolder();
......
865 env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
866}
和BinderProxy一樣的套路,我們發現在native其實就是new一個JavaBBinderHolder對象,並把它設置到Binder的mObject成員變量中,這裏就不多說,下面我們看看JavaBBinderHolder實現。
362class JavaBBinderHolder : public RefBase
363{
364public:
365 sp<JavaBBinder> get(JNIEnv* env, jobject obj)
366 {
367 AutoMutex _l(mLock);
368 sp<JavaBBinder> b = mBinder.promote();
369 if (b == NULL) {
370 b = new JavaBBinder(env, obj); // (1)
371 mBinder = b;
......
384
385private:
386 Mutex mLock;
387 wp<JavaBBinder> mBinder; // (2)
388};
最終JavaBBinderHolder 通過其get方法返回JavaBBinder對象,這裏先不管JavaBBinderHolder.get在哪兒被調用,先看看JavaBBinder的定義。
265class JavaBBinder : public BBinder
266{
267public:
268 JavaBBinder(JNIEnv* env, jobject object)
269 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
270 {
271 ALOGV("Creating JavaBBinder %p\n", this);
272 android_atomic_inc(&gNumLocalRefs);
273 incRefsCreated(env);
274 }
關鍵來了,原來JavaBBinder就是一個BBinder對象,所以和我們一開始說的一樣,從Binder繼承的Service在本地其實是一個BBinder,而且這個JavaBBinder還持有實體IBinder的引用(mObject(env->NewGlobalRef(object))),其把實體IBinder對象保存在mObject中,而這個對象就是JAVA層實現的Service。在Binder驅動把業務邏輯轉到Service宿主進程的時候最終會執行到JavaBBinder的onTransact方法。
295 virtual status_t onTransact(
296 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
297 {
298 JNIEnv* env = javavm_to_jnienv(mVM);
......
308 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
309 code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
從上面代碼我們知道最終會把調用轉到JAVA層實現的Service的execTransact方法,這個execTransact就是JAVA層的Binder對象的一個方法,Service重載這個方法從而完成把邏輯轉到業務層的調度。
接下來我們看下BBinder的定義。
在文件frameworks/native/libs/binder/Binder.cpp中找到localBinder的定義。
199BBinder* BBinder::localBinder()
200{
201 return this;
202}
這裏我們看到了BBinder對本地接口返回是自身對象,遠程接口返回的是NULL(在IBinder中實現),到這裏就明白了爲什麼實現Binder的服務就是一個本地對象。
最後看下Parcel的實現,這裏JAVA層的Parcel就不講了,因爲都是一個套路,JAVA層的Parcel只是一個容器,實際實現在本地的Parcel類中。
Parcel
這裏JAVA層的Parcel接口對應實現在下面文件中。
frameworks/base/core/jni/android_os_Parcel.cpp
這裏重點看下nativeReadStrongBinder的實現。
451static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
452{
453 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
454 if (parcel != NULL) {
455 return javaObjectForIBinder(env, parcel->readStrongBinder()); // (1)
456 }
457 return NULL;
458}
這裏調用javaObjectForIBinder生成JAVA對象,其實就是BinderProxy,在看javaObjectForIBinder方法之前,先看下parcel->readStrongBinder()這個怎麼返回IBinder對象的,經過層層調用最終會進入如下方法:
323status_t unflatten_binder(const sp<ProcessState>& proc,
324 const Parcel& in, wp<IBinder>* out)
325{
326 const flat_binder_object* flat = in.readObject(false);
327
328 if (flat) {
329 switch (flat->type) {
......
342 case BINDER_TYPE_HANDLE:
343 case BINDER_TYPE_WEAK_HANDLE:
344 *out = proc->getWeakProxyForHandle(flat->handle); // (1)
345 return finish_unflatten_binder(
346 static_cast<BpBinder*>(out->unsafe_get()), *flat, in);
347 }
348 }
349 return BAD_TYPE;
350}
這裏有個flat_binder_object結構,我們簡單說下,這個結構其實就是IBinder對象在Binder驅動層的二進制描述,存儲了IBinder的相關信息。我們重點看下代碼(1)出的邏輯,這裏最終調用還是ProcessSate的getWeakProxyForHandle方法,這個方法上面介紹過,其實就是返回BpBinder對象,而且根據handle做了緩存處理。
這樣我們知道javaObjectForIBinder的第二個參數其實就是BpBinder類型的IBinder對象,這個方法上面也介紹過了,就是生成BinderProxy對象,然後把BpBinder類型的IBinder設置給BinderProxy的成員變量mObject。
到這裏我們把和Binder調用流程相關的幾個關鍵類介紹完了,有了這個基礎,後面講解Binder的調用流程就會輕鬆多了。
本系列文章均爲原創,主要總結作者多年在軟件行業的一些經驗,和大家共同學習、進步,轉載請註明出處,謝謝!