鍍金池/ 教程/ Android/ 第2章? 深入理解 Java Binder 和 MessageQueue
第2章? 深入理解 Java Binder 和 MessageQueue
第7章? 深入理解 ContentProvider
第5章? 深入理解 PowerManagerService
第3章? 深入理解 SystemServer
第8章? 深入理解ContentService 和 AccountManagerService
第1章?開發(fā)環(huán)境部署
第4章? 深入理解 PackageManagerService
第6章?深入理解ActivityManagerService

第2章? 深入理解 Java Binder 和 MessageQueue

本章主要內(nèi)容:

·??介紹Binder系統(tǒng)的Java層框架

·??介紹MessageQueue

本章所涉及的源代碼文件名及位置:

·??IBinder.java

frameworks/base/core/java/android/os/IBinder.java

·??Binder.java

frameworks/base/core/java/android/os/Binder.java

·??BinderInternal.java

frameworks/base/core/java/com/android/intenal/os/BinderInternal.java

·??android_util_Binder.cpp

frameworks/base/core/jni/android_util_Binder.cpp

·??SystemServer.java

frameworks/base/services/java/com/android/servers/SystemServer.java

·??ActivityManagerService.java

frameworks/base/services/java/com/android/servers/ActivityManagerService.java

·??ServiceManager.java

frameworks/base/core/java/android/os/ServiceManager.java

·??ServcieManagerNative.java

frameworks/base/core/java/android/os/ ServcieManagerNative.java

·??MessageQueue.java

frameworks/base/core/java/android/os/MessageQueue.java

·??android_os_MessageQueue.cpp

frameworks/base/core/jni/android_os_MessageQueue.cpp

·??Looper.cpp

frameworks/base/native/android/Looper.cpp

·??Looper.h

frameworks/base/include/utils/Looper.h

·??android_app_NativeActivity.cpp

frameworks/base/core/jni/android_app_NativeActivity.cpp

2.1 ?概述

以本章做為本書Android分析之旅的開篇,將重點(diǎn)關(guān)注兩個(gè)基礎(chǔ)知識(shí)點(diǎn),它們是:

·??Binder系統(tǒng)在Java世界是如何布局和工作的

·??MessageQueue的新職責(zé)

先來(lái)分析Java層中的Binder。

建議讀者先閱讀《深入理解Android:卷I》(以下簡(jiǎn)稱“卷I”)的第6章“深入理解Binder”。網(wǎng)上有樣章可下載。

2.2? Java層中的Binder分析

2.2.1? Binder架構(gòu)總覽

如果讀者讀過(guò)卷I第6章“深入理解Binder”,相信就不會(huì)對(duì)Binder架構(gòu)中代表Client的Bp端及代表Server的Bn端感到陌生。Java層中Binder實(shí)際上也是一個(gè)C/S架構(gòu),而且其在類的命名上盡量保持與Native層一致,因此可認(rèn)為,Java層的Binder架構(gòu)是Native層Binder架構(gòu)的一個(gè)鏡像。Java層的Binder架構(gòu)中的成員如圖2-1所示。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter2/image001.png" alt="image" />

圖2-1 ?Java層中的Binder家族

由圖2-1可知:

·??系統(tǒng)定義了一個(gè)IBinder接口類以及DeathRecepient接口。

·??Binder類和BinderProxy類分別實(shí)現(xiàn)了IBinder接口。其中Binder類作為服務(wù)端的Bn的代表,而BinderProxy作為客戶端的Bp的代表。

·??系統(tǒng)中還定義一個(gè)BinderInternal類。該類是一個(gè)僅供Binder框架使用的類。它內(nèi)部有一個(gè)GcWatcher類,該類專門用于處理和Binder相關(guān)的垃圾回收。

·??Java層同樣提供一個(gè)用于承載通信數(shù)據(jù)的Parcel類。

注意,IBinder接口類中定義了一個(gè)叫FLAG_ONEWAY的整型,該變量的意義非常重要。當(dāng)客戶端利用Binder機(jī)制發(fā)起一個(gè)跨進(jìn)程的函數(shù)調(diào)用時(shí),調(diào)用方(即客戶端)一般會(huì)阻塞,直到服務(wù)端返回結(jié)果。這種方式和普通的函數(shù)調(diào)用是一樣的。但是在調(diào)用Binder函數(shù)時(shí),在指明了FLAG_ONEWAY標(biāo)志后,調(diào)用方只要把請(qǐng)求發(fā)送到Binder驅(qū)動(dòng)即可返回,而不用等待服務(wù)端的結(jié)果,這就是一種所謂的非阻塞方式。在Native層中,涉及的Binder調(diào)用基本都是阻塞的,但是在Java層的framework中,使用FLAG_ONEWAY進(jìn)行Binder調(diào)用的情況非常多,以后經(jīng)常會(huì)碰到。

思考 使用FLAG_ONEWAY進(jìn)行函數(shù)調(diào)用的程序在設(shè)計(jì)上有什么特點(diǎn)?這里簡(jiǎn)單分析一下:對(duì)于使用FLAG_ONEWAY的函數(shù)來(lái)說(shuō),客戶端僅向服務(wù)端發(fā)出了請(qǐng)求,但是并不能確定服務(wù)端是否處理了該請(qǐng)求。所以,客戶端一般會(huì)向服務(wù)端注冊(cè)一個(gè)回調(diào)(同樣是跨進(jìn)程的Binder調(diào)用),一旦服務(wù)端處理了該請(qǐng)求,就會(huì)調(diào)用此回調(diào)來(lái)通知客戶端處理結(jié)果。當(dāng)然,這種回調(diào)函數(shù)也大多采用FLAG_ONEWAY的方式。

2.2.2? 初始化Java層Binder框架

雖然Java層Binder系統(tǒng)是Native層Binder系統(tǒng)的一個(gè)Mirror,但這個(gè)Mirror終歸還需借助Native層Binder系統(tǒng)來(lái)開展工作,即Mirror和Native層Binder有著千絲萬(wàn)縷的關(guān)系,一定要在Java層Binder正式工作之前建立這種關(guān)系。下面分析Java層Binder框架是如何初始化的。

在Android系統(tǒng)中,在Java初創(chuàng)時(shí)期,系統(tǒng)會(huì)提前注冊(cè)一些JNI函數(shù),其中有一個(gè)函數(shù)專門負(fù)責(zé)搭建Java Binder和Native Binder交互關(guān)系,該函數(shù)是register_android_os_Binder,代碼如下:

[-->android_util_Binder.cpp]

int register_android_os_Binder(JNIEnv* env)

{

??? //初始化Java Binder類和Native層的關(guān)系

??? if(int_register_android_os_Binder(env) < 0)

???????return -1;

??? //初始化Java BinderInternal類和Native層的關(guān)系

??? if(int_register_android_os_BinderInternal(env) < 0)

???????return -1;

?? //初始化Java BinderProxy類和Native層的關(guān)系

??? if(int_register_android_os_BinderProxy(env) < 0)

???????return -1;

?? //初始化Java Parcel類和Native層的關(guān)系

??? if(int_register_android_os_Parcel(env) < 0)

???????return -1;

??? return0;

}

據(jù)上面的代碼可知,register_android_os_Binder函數(shù)完成了Java Binder架構(gòu)中最重要的4個(gè)類的初始化工作。我們重點(diǎn)關(guān)注前3個(gè)。

1. ?Binder類的初始化

int_register_android_os_Binder函數(shù)完成了Binder類的初始化工作,代碼如下:

[-->android_util_Binder.cpp]

static int int_register_android_os_Binder(JNIEnv*env)

{

? jclassclazz;

? //kBinderPathName為Java層中Binder類的全路徑名,“android/os/Binder“

? clazz =env->FindClass(kBinderPathName);

? /*

? gBinderOffSets是一個(gè)靜態(tài)類對(duì)象,它專門保存Binder類的一些在JNI層中使用的信息,

? 如成員函數(shù)execTranscat的methodID,Binder類中成員mObject的fildID

? */

???gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);

???gBinderOffsets.mExecTransact

?? ??????????????????= env->GetMethodID(clazz,"execTransact", "(IIII)Z");

???gBinderOffsets.mObject

??????? ?????????????= env->GetFieldID(clazz,"mObject", "I");

?? //注冊(cè)Binder類中native函數(shù)的實(shí)現(xiàn)

??? returnAndroidRuntime::registerNativeMethods(

?????? ?????????????????????env, kBinderPathName,

??????? ????????????????????gBinderMethods,NELEM(gBinderMethods));

}

從上面代碼可知,gBinderOffsets對(duì)象保存了和Binder類相關(guān)的某些在JNI層中使用的信息。

建議 如果讀者對(duì)JNI不是很清楚,可參閱卷I第2章“深入理解JNI”。

2. ?BinderInternal類的初始化

下一個(gè)初始化的類是BinderInternal,其代碼在int_register_android_os_BinderInternal函數(shù)中。

[-->android_util_Binder.cpp]

static intint_register_android_os_BinderInternal(JNIEnv* env)

{

? ?jclass clazz;

? ?//根據(jù)BinderInternal的全路徑名找到代表該類的jclass對(duì)象。全路徑名為

? ?// “com/android/internal/os/BinderInternal”

? ?clazz =env->FindClass(kBinderInternalPathName);

? ?//gBinderInternalOffsets也是一個(gè)靜態(tài)對(duì)象,用來(lái)保存BinderInternal類的一些信息

? ?gBinderInternalOffsets.mClass = (jclass)env->NewGlobalRef(clazz);

? ?//獲取forceBinderGc的methodID

??gBinderInternalOffsets.mForceGc

?????? ??????????= env->GetStaticMethodID(clazz,"forceBinderGc", "()V");

? ???//注冊(cè)BinderInternal類中native函數(shù)的實(shí)現(xiàn)

?? ?return AndroidRuntime::registerNativeMethods(

????????????????????????env,kBinderInternalPathName,

??????? ?????????????????gBinderInternalMethods, NELEM(gBinderInternalMethods));

}

int_register_android_os_BinderInternal的工作內(nèi)容和int_register_android_os_Binder的工作內(nèi)容類似:

·??獲取一些有用的methodID和fieldID。這表明JNI層一定會(huì)向上調(diào)用Java層的函數(shù)。

·??注冊(cè)相關(guān)類中native函數(shù)的實(shí)現(xiàn)。

3. ?BinderProxy類的初始化

int_register_android_os_BinderProxy完成了BinderProxy類的初始化工作,代碼稍顯復(fù)雜,如下所示:

[-->android_util_Binder.cpp]

static intint_register_android_os_BinderProxy(JNIEnv* env)

{

??? jclassclazz;

??

? ?clazz =env->FindClass("java/lang/ref/WeakReference");

? ?//gWeakReferenceOffsets用來(lái)和WeakReference類打交道

? ?gWeakReferenceOffsets.mClass = (jclass)env->NewGlobalRef(clazz);

? ?//獲取WeakReference類get函數(shù)的MethodID

???gWeakReferenceOffsets.mGet= env->GetMethodID(clazz, "get",

?????????????????????????????????? ?"()Ljava/lang/Object;");

?? ?clazz = env->FindClass("java/lang/Error");

??? //gErrorOffsets用來(lái)和Error類打交道

???gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);

?

??? clazz =env->FindClass(kBinderProxyPathName);

??? //gBinderProxyOffsets用來(lái)和BinderProxy類打交道

???gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);

???gBinderProxyOffsets.mConstructor= env->GetMethodID(clazz,"<init>", "()V");

??? ...... //獲取BinderProxy的一些信息

?? ?clazz =env->FindClass("java/lang/Class");

??? //gClassOffsets用來(lái)和Class類打交道

??? gClassOffsets.mGetName=env->GetMethodID(clazz,

????????????????????????????? "getName","()Ljava/lang/String;");

??? //注冊(cè)BinderProxy native函數(shù)的實(shí)現(xiàn)

??? returnAndroidRuntime::registerNativeMethods(env,

???????? ?kBinderProxyPathName,gBinderProxyMethods,

?????????????????????????????? ?NELEM(gBinderProxyMethods));

}

據(jù)上面代碼可知,int_register_android_os_BinderProxy函數(shù)除了初始化BinderProxy類外,還獲取了WeakReference類和Error類的一些信息??磥?lái)BinderProxy對(duì)象的生命周期會(huì)委托WeakReference來(lái)管理,難怪JNI層會(huì)獲取該類get函數(shù)的MethodID。

至此,Java Binder幾個(gè)重要成員的初始化已完成,同時(shí)在代碼中定義了幾個(gè)全局靜態(tài)對(duì)象,分別是gBinderOffsets、gBinderInternalOffsets和gBinderProxyOffsets。

這幾個(gè)對(duì)象的命名中都有一個(gè)Offsets,我覺(jué)得這非常別扭,不知道讀者是否有同感。

框架的初始化其實(shí)就是提前獲取一些JNI層的使用信息,如類成員函數(shù)的MethodID,類成員變量的fieldID等。這項(xiàng)工作是必需的,因?yàn)樗芄?jié)省每次使用時(shí)獲取這些信息的時(shí)間。當(dāng)Binder調(diào)用頻繁時(shí),這些時(shí)間累積起來(lái)還是不容小覷的。

下面我們通過(guò)一個(gè)例子來(lái)分析Java Binder的工作流程。

2.2.3? 窺一斑,可見(jiàn)全豹乎

這個(gè)例子源自ActivityManagerService,我們?cè)噲D通過(guò)它揭示Java層Binder的工作原理。先來(lái)描述一下該例子的分析步驟:

·??首先分析AMS如何將自己注冊(cè)到ServiceManager。

·??然后分析AMS如何響應(yīng)客戶端的Binder調(diào)用請(qǐng)求。

本例的起點(diǎn)是setSystemProcess,其代碼如下所示:

[-->ActivityManagerService.java]

public static void setSystemProcess() {

?try {

?? ?????ActivityManagerService m = mSelf;

??????? //將ActivityManagerService服務(wù)注冊(cè)到ServiceManager中

???????ServiceManager.addService("activity", m);......

????? }

?? ......

?? return;

}

上面所示代碼行的目的是將ActivityManagerService服務(wù)加到ServiceManager中。ActivityManagerService(以后簡(jiǎn)稱AMS)是Android核心服務(wù)中的核心,我們以后會(huì)經(jīng)常和它打交道。

大家知道,整個(gè)Android系統(tǒng)中有一個(gè)Native的ServiceManager(以后簡(jiǎn)稱SM)進(jìn)程,它統(tǒng)籌管理Android系統(tǒng)上的所有Service。成為一個(gè)Service的首要條件是先在SM中注冊(cè)。下面來(lái)看Java層的Service是如何向SM注冊(cè)的。

1.? 向ServiceManager注冊(cè)服務(wù)

(1) 創(chuàng)建ServiceManagerProxy

向SM注冊(cè)服務(wù)的函數(shù)叫addService,其代碼如下:

[-->ServiceManager.java]

public static void addService(String name, IBinderservice) {

? try {

????????? //getIServiceManager返回什么

??? ?????getIServiceManager().addService(name,service);

???? }

???? ......

?}

//分析getIServiceManager函數(shù)

private static IServiceManagergetIServiceManager() {

??? ......

??? //調(diào)用asInterface,傳遞的參數(shù)類型為IBinder???????

??? sServiceManager= ServiceManagerNative.asInterface(

??????????????????????? BinderInternal.getContextObject());

??? returnsServiceManager;

}

asInterface的參數(shù)為BinderInternal.getContextObject的返回值。這是一個(gè)native的函數(shù),其實(shí)現(xiàn)的代碼為:

[-->android_util_Binder.cpp]

static jobjectandroid_os_BinderInternal_getContextObject(

JNIEnv* env, jobject clazz)

{

?? /*

?? ?下面這句代碼,我們?cè)诰鞩第6章詳細(xì)分析過(guò),它將返回一個(gè)BpProxy對(duì)象,其中

??? NULL(即0,用于標(biāo)識(shí)目的端)指定Proxy通信的目的端是ServiceManager

?? */

??? sp<IBinder>b = ProcessState::self()->getContextObject(NULL);

??? //由Native對(duì)象創(chuàng)建一個(gè)Java對(duì)象,下面分析該函數(shù)

??? returnjavaObjectForIBinder(env, b);

}

[-->android_util_Binder.cpp]

jobject javaObjectForIBinder(JNIEnv* env, constsp<IBinder>& val)

{

?? //mProxyLock是一個(gè)全局的靜態(tài)CMutex對(duì)象

??? AutoMutex_l(mProxyLock);

?

? /*

??? val對(duì)象實(shí)際類型是BpBinder,讀者可自行分析BpBinder.cpp中的findObject函數(shù)。

??? 事實(shí)上,在Native層的BpBinder中有一個(gè)ObjectManager,它用來(lái)管理在Native BpBinder

??? 上創(chuàng)建的Java BpBinder對(duì)象。下面這個(gè)findObject用來(lái)判斷gBinderProxyOffsets

??? 是否已經(jīng)保存在ObjectManager中。如果是,那就需要?jiǎng)h除這個(gè)舊的object

? */

jobject object =(jobject)val->findObject(&gBinderProxyOffsets);

??? if(object != NULL) {

???????jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet);

???????android_atomic_dec(&gNumProxyRefs);

???????val->detachObject(&gBinderProxyOffsets);

???????env->DeleteGlobalRef(object);

??? }

???

??? ?//創(chuàng)建一個(gè)新的BinderProxy對(duì)象,并注冊(cè)到Native BpBinder對(duì)象的ObjectManager中

??????? object= env->NewObject(gBinderProxyOffsets.mClass,

??????????????????????????? gBinderProxyOffsets.mConstructor);

??? if(object != NULL) {

???????env->SetIntField(object, gBinderProxyOffsets.mObject,(int)val.get());

???????val->incStrong(object);

???????jobject refObject = env->NewGlobalRef(

???????????????env->GetObjectField(object, gBinderProxyOffsets.mSelf));

??????? /*

??????? 將這個(gè)新創(chuàng)建的BinderProxy對(duì)象注冊(cè)(attach)到BpBinder的ObjectManager中,

???????同時(shí)注冊(cè)一個(gè)回收函數(shù)proxy_cleanup。當(dāng)BinderProxy對(duì)象撤銷(detach)的時(shí)候,

??????? 該函數(shù)會(huì) 被調(diào)用,以釋放一些資源。讀者可自行研究proxy_cleanup函數(shù)。

????? */

???????val->attachObject(&gBinderProxyOffsets, refObject,

?????????????????????????????jnienv_to_javavm(env),proxy_cleanup);

?

??????? //DeathRecipientList保存了一個(gè)用于死亡通知的list

??????? sp<DeathRecipientList>drl = new DeathRecipientList;

???????drl->incStrong((void*)javaObjectForIBinder);

??????? //將死亡通知list和BinderProxy對(duì)象聯(lián)系起來(lái)

???????env->SetIntField(object, gBinderProxyOffsets.mOrgue,

???????????????????????????? reinterpret_cast<jint>(drl.get()));

??????? //增加該P(yáng)roxy對(duì)象的引用計(jì)數(shù)

?????? ?android_atomic_inc(&gNumProxyRefs);

??????? //下面這個(gè)函數(shù)用于垃圾回收。創(chuàng)建的Proxy對(duì)象一旦超過(guò)200個(gè),該函數(shù)

??????? //將調(diào)用BinderInter類的ForceGc做一次垃圾回收

???????incRefsCreated(env);

??? }

?

??? returnobject;

}

BinderInternal.getContextObject的代碼有點(diǎn)多,簡(jiǎn)單整理一下,可知該函數(shù)完成了以下兩個(gè)工作:

·??創(chuàng)建了一個(gè)Java層的BinderProxy對(duì)象。

·??通過(guò)JNI,該BinderProxy對(duì)象和一個(gè)Native的BpProxy對(duì)象掛鉤,而該BpProxy對(duì)象的通信目標(biāo)就是ServiceManager。

大家還記得在Native層Binder中那個(gè)著名的interface_cast宏嗎?在Java層中,雖然沒(méi)有這樣的宏,但是定義了一個(gè)類似的函數(shù)asInterface。下面來(lái)分析ServiceManagerNative類的asInterface函數(shù),其代碼如下:

[-->ServiceManagerNative.java]

static public IServiceManager asInterface(IBinderobj)

?{

???????...... //以obj為參數(shù),創(chuàng)建一個(gè)ServiceManagerProxy對(duì)象

???????return new ServiceManagerProxy(obj);

?}

上面代碼和Native層interface_cast非常類似,都是以一個(gè)BpProxy對(duì)象為參數(shù)構(gòu)造一個(gè)和業(yè)務(wù)相關(guān)的Proxy對(duì)象,例如這里的ServiceManagerProxy對(duì)象。ServiceManagerProxy對(duì)象的各個(gè)業(yè)務(wù)函數(shù)會(huì)將相應(yīng)請(qǐng)求打包后交給BpProxy對(duì)象,最終由BpProxy對(duì)象發(fā)送給Binder驅(qū)動(dòng)以完成一次通信。

提示 實(shí)際上BpProxy也不會(huì)和Binder驅(qū)動(dòng)交互,真正和Binder驅(qū)動(dòng)交互的是IPCThreadState。

(2) addService函數(shù)分析

現(xiàn)在來(lái)分析ServiceManagerProxy的addService函數(shù),其代碼如下:

[-->ServcieManagerNative.java]

public void addService(String name, IBinderservice)

??????????? ???????????????throws RemoteException {

???????Parcel data = Parcel.obtain();

???????Parcel reply = Parcel.obtain();

???????data.writeInterfaceToken(IServiceManager.descriptor);

???????data.writeString(name);

??????? //注意下面這個(gè)writeStrongBinder函數(shù),后面我們會(huì)詳細(xì)分析它

???????data.writeStrongBinder(service);

???????//mRemote實(shí)際上就是BinderProxy對(duì)象,調(diào)用它的transact,將封裝好的請(qǐng)求數(shù)據(jù)

?????? //發(fā)送出去

???????mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);

???????reply.recycle();

???????data.recycle();

}

BinderProxy的transact,是一個(gè)native函數(shù),其實(shí)現(xiàn)函數(shù)的代碼如下所示:

[-->android_util_Binder.cpp]

static jbooleanandroid_os_BinderProxy_transact(JNIEnv* env, jobject obj,

???????????????????????????????????????????jintcode, jobject dataObj,

???????????????????????????????????????????jobject replyObj, jint flags)

{

??????? ......

??? //從Java的Parcel對(duì)象中得到Native的Parcel對(duì)象

??? Parcel*data = parcelForJavaObject(env, dataObj);

??? if (data== NULL) {

???????return JNI_FALSE;

??? }

??? //得到一個(gè)用于接收回復(fù)的Parcel對(duì)象

??? Parcel*reply = parcelForJavaObject(env, replyObj);

??? if(reply == NULL && replyObj != NULL) {

???????return JNI_FALSE;

??? }

??? //從Java的BinderProxy對(duì)象中得到之前已經(jīng)創(chuàng)建好的那個(gè)Native的BpBinder對(duì)象

??? IBinder*target = (IBinder*)

???????env->GetIntField(obj, gBinderProxyOffsets.mObject);

??? ......

??? //通過(guò)Native的BpBinder對(duì)象,將請(qǐng)求發(fā)送給ServiceManager

??? status_terr = target->transact(code, *data, reply, flags);

?? ?......

?? ?signalExceptionForError(env, obj, err);

??? returnJNI_FALSE;

}

看了上面的代碼會(huì)發(fā)現(xiàn),Java層的Binder最終還是要借助Native的Binder進(jìn)行通信的。

關(guān)于Binder這套架構(gòu),筆者有一個(gè)體會(huì)愿和讀者一起討論分析。

從架構(gòu)的角度看,在Java中搭建了一整套框架,如IBinder接口,Binder類和BinderProxy類。但是從通信角度看,不論架構(gòu)的編寫采用的是Native語(yǔ)言還是Java語(yǔ)言,只要把請(qǐng)求傳遞到Binder驅(qū)動(dòng)就可以了,所以通信的目的是向binder發(fā)送請(qǐng)求和接收回復(fù)。在這個(gè)目的之上,考慮到軟件的靈活性和可擴(kuò)展性,于是編寫了一個(gè)架構(gòu)。反過(guò)來(lái)說(shuō),也可以不使用架構(gòu)(即沒(méi)有使用任何接口、派生之類的東西)而直接和binder交互,例如ServiceManager作為Binder的一個(gè)核心程序,就是直接讀取/dev/binder設(shè)備,獲取并處理請(qǐng)求。從這一點(diǎn)上看,Binder的目的雖是簡(jiǎn)單的(即打開binder設(shè)備,然后讀請(qǐng)求和寫回復(fù)),但是架構(gòu)是復(fù)雜的(編寫各種接口類和封裝類等)。我們?cè)谘芯吭创a時(shí),一定要先搞清楚目的。實(shí)現(xiàn)只不過(guò)是達(dá)到該目的的一種手段和方式。脫離目的的實(shí)現(xiàn),如緣木求魚,很容易偏離事物本質(zhì)。

在對(duì)addService進(jìn)行分析時(shí),我們?cè)崾緒riteStrongBinder是一個(gè)特別的函數(shù)。那么它特別在哪里呢?

(3) 三人行之Binder、JavaBBinderHolder和JavaBBinder

ActivityManagerService從ActivityManagerNative類派生,并實(shí)現(xiàn)了一些接口,其中和Binder的相關(guān)的只有這個(gè)ActivityManagerNative類,其原型如下:

[-->ActivityManagerNative.java]

public abstract class ActivityManagerNative

????????????????????????? extends Binder

????????????????????????? implementsIActivityManager

ActivityManagerNative從Binder派生,并實(shí)現(xiàn)了IActivityManager接口。下面來(lái)看ActivityManagerNative的構(gòu)造函數(shù):

[-->ActivityManagerNative.java]

public ActivityManagerNative() {

???????attachInterface(this, descriptor);//該函數(shù)很簡(jiǎn)單,讀者可自行分析

??? }

//這是ActivityManagerNative父類的構(gòu)造函數(shù),即Binder的構(gòu)造函數(shù)

public Binder() {

???????init();

}

Binder構(gòu)造函數(shù)中會(huì)調(diào)用native的init函數(shù),其實(shí)現(xiàn)的代碼如下:

[-->android_util_Binder.cpp]

static void android_os_Binder_init(JNIEnv* env,jobject obj)

{

??? //創(chuàng)建一個(gè)JavaBBinderHolder對(duì)象

???JavaBBinderHolder* jbh = new JavaBBinderHolder();

??? ?bh->incStrong((void*)android_os_Binder_init);

?? //將這個(gè)JavaBBinderHolder對(duì)象保存到Java Binder對(duì)象的mObject成員中

???env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);

}

從上面代碼可知,Java的Binder對(duì)象將和一個(gè)Native的JavaBBinderHolder對(duì)象相關(guān)聯(lián)。那么,JavaBBinderHolder是何方神圣呢?其定義如下:

[-->android_util_Binder.cpp]

class JavaBBinderHolder : public RefBase

{

public:

???sp<JavaBBinder> get(JNIEnv* env, jobject obj)

??? {

???????AutoMutex _l(mLock);

???????sp<JavaBBinder> b = mBinder.promote();

??????? if(b == NULL) {

??????????//創(chuàng)建一個(gè)JavaBBinder,obj實(shí)際上是Java層中的Binder對(duì)象

???????????b = new JavaBBinder(env, obj);

???????????mBinder = b;

????? ?}

???????return b;

??? }

?? ?......

private:

???Mutex?????????? mLock;

???wp<JavaBBinder> mBinder;

};

從派生關(guān)系上可以發(fā)現(xiàn),JavaBBinderHolder僅從RefBase派生,所以它不屬于Binder家族。Java層的Binder對(duì)象為什么會(huì)和Native層的一個(gè)與Binder家族無(wú)關(guān)的對(duì)象綁定呢?仔細(xì)觀察JavaBBinderHolder的定義可知:JavaBBinderHolder類的get函數(shù)中創(chuàng)建了一個(gè)JavaBBinder對(duì)象,這個(gè)對(duì)象就是從BnBinder派生的。

那么,這個(gè)get函數(shù)是在哪里調(diào)用的?答案在下面這句代碼中:

//其中,data是Parcel對(duì)象,service此時(shí)還是ActivityManagerService

data.writeStrongBinder(service);

writeStrongBinder會(huì)做一個(gè)替換工作,下面是它的native代碼實(shí)現(xiàn):

[-->android_util_Binder.cpp]

static void android_os_Parcel_writeStrongBinder(JNIEnv*env,

?????????????????????????????????????????????? jobjectclazz, jobject object)

{

?? //parcel是一個(gè)Native的對(duì)象,writeStrongBinder的真正參數(shù)是

?//ibinderForJavaObject的返回值

? conststatus_t err = parcel->writeStrongBinder(

??????????????????????????????????? ibinderForJavaObject(env,object));

}

[-->android_util_Binder.cpp]

sp<IBinder> ibinderForJavaObject(JNIEnv*env, jobject obj)

{

?? //如果Java的obj是Binder類,則首先獲得JavaBBinderHolder對(duì)象,然后調(diào)用

? //它的get函數(shù)。而這個(gè)get將返回一個(gè)JavaBBinder

? if(env->IsInstanceOf(obj, gBinderOffsets.mClass)) {

???? JavaBBinderHolder*jbh = (JavaBBinderHolder*)env->GetIntField(obj,

????????????????????????????????????? gBinderOffsets.mObject);

???????return jbh != NULL ? jbh->get(env, obj) : NULL;

??? }

??? //如果obj是BinderProxy類,則返回Native的BpBinder對(duì)象

??? if(env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {

???????return (IBinder*)

???????????env->GetIntField(obj, gBinderProxyOffsets.mObject);

??? }

?? returnNULL;

}

根據(jù)上面的介紹會(huì)發(fā)現(xiàn),addService實(shí)際添加到Parcel的并不是AMS本身,而是一個(gè)叫JavaBBinder的對(duì)象。正是將它最終傳遞到Binder驅(qū)動(dòng)。

讀者此時(shí)容易想到,Java層中所有的Binder對(duì)應(yīng)的都是這個(gè)JavaBBinder。當(dāng)然,不同的Binder對(duì)象對(duì)應(yīng)不同的JavaBBinder對(duì)象。

圖2-2展示了Java Binder、JavaBBinderHolder和JavaBBinder的關(guān)系。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter2/image002.png" alt="image" />

圖2-2 JavaBinder、JavaBBinderHolder和JavaBBinder三者的關(guān)系

從圖2-2可知:

·??Java層的Binder通過(guò)mObject指向一個(gè)Native層的JavaBBInderHolder對(duì)象。

·??Native層的JavaBBinderHolder對(duì)象通過(guò)mBinder成員變量指向一個(gè)Native的JavaBBinder對(duì)象。

·??Native的JavaBBinder對(duì)象又通過(guò)mObject變量指向一個(gè)Java層的Binder對(duì)象。

為什么不直接讓Java層的Binder對(duì)象指向Native層的JavaBBinder對(duì)象呢?由于缺乏設(shè)計(jì)文檔,這里不便妄加揣測(cè),但從JavaBBinderHolder的實(shí)現(xiàn)上來(lái)分析,估計(jì)和垃圾回收(內(nèi)存管理)有關(guān),因?yàn)镴avaBBinderHolder中的mBinder對(duì)象的類型被定義成弱引用wp了。

建議 對(duì)此,如果讀者有更好的解釋,不妨與大家分享一下。

2.? ActivityManagerService響應(yīng)請(qǐng)求

初見(jiàn)JavaBBinde時(shí),多少有些吃驚?;叵胍幌翹ative層的Binder架構(gòu):雖然在代碼中調(diào)用的是Binder類提供的接口,但其對(duì)象卻是一個(gè)實(shí)際的服務(wù)端對(duì)象,例如MediaPlayerService對(duì)象,AudioFlinger對(duì)象。

而Java層的Binder架構(gòu)中,JavaBBinder卻是一個(gè)和業(yè)務(wù)完全無(wú)關(guān)的對(duì)象。那么,這個(gè)對(duì)象如何實(shí)現(xiàn)不同業(yè)務(wù)呢?

為回答此問(wèn)題,我們必須看它的onTransact函數(shù)。當(dāng)收到請(qǐng)求時(shí),系統(tǒng)會(huì)調(diào)用這個(gè)函數(shù)。

關(guān)于這個(gè)問(wèn)題,建議讀者閱讀卷I第六章《深入理解Binder》。

[-->android_util_Binder.cpp]

virtual status_t onTransact(

???????uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags =0)

{

???????JNIEnv* env = javavm_to_jnienv(mVM);

???????IPCThreadState* thread_state = IPCThreadState::self();

???????.......

?????? //調(diào)用Java層Binder對(duì)象的execTranscat函數(shù)

???????jboolean res = env->CallBooleanMethod(mObject,

????????????????????gBinderOffsets.mExecTransact,code,

???????????????????(int32_t)&data,(int32_t)reply, flags);

??????? ......

???????return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;

}

就本例而言,上面代碼中的mObject就是ActivityManagerService,現(xiàn)在調(diào)用它的execTransact函數(shù),該函數(shù)在Binder類中實(shí)現(xiàn),具體代碼如下:

?[-->Binder.java]

private boolean execTransact(int code, intdataObj, int replyObj,int flags) {

???????Parcel data = Parcel.obtain(dataObj);

???????Parcel reply = Parcel.obtain(replyObj);

???????boolean res;

??????? try{

???????????//調(diào)用onTransact函數(shù),派生類可以重新實(shí)現(xiàn)這個(gè)函數(shù),以完成業(yè)務(wù)功能

???????????res = onTransact(code, data, reply, flags);

??????? }......

???????reply.recycle();

???????data.recycle();

???????return res;

??? }

}

ActivityManagerNative類實(shí)現(xiàn)了onTransact函數(shù),代碼如下:

[-->ActivityManagerNative.java]

public boolean onTransact(int code, Parcel data,Parcel reply, int flags)

???????????throws RemoteException {

???????switch (code) {

??????? caseSTART_ACTIVITY_TRANSACTION:

??????? {

???????????data.enforceInterface(IActivityManager.descriptor);

???????????IBinder b = data.readStrongBinder();

???????????......

?????????? //再由ActivityManagerService實(shí)現(xiàn)業(yè)務(wù)函數(shù)startActivity

?????????? intresult = startActivity(app, intent, resolvedType,

???????????????????grantedUriPermissions, grantedMode, resultTo, resultWho,

???????????????????requestCode, onlyIfNeeded, debug, profileFile,

???????????????????profileFd, autoStopProfiler);

???????????reply.writeNoException();

???????????reply.writeInt(result);

???????????return true;

}

由此可以看出,JavaBBinder僅是一個(gè)傳聲筒,它本身不實(shí)現(xiàn)任何業(yè)務(wù)函數(shù),其工作是:

·??當(dāng)它收到請(qǐng)求時(shí),只是簡(jiǎn)單地調(diào)用它所綁定的Java層Binder對(duì)象的exeTransact。

·??該Binder對(duì)象的exeTransact調(diào)用其子類實(shí)現(xiàn)的onTransact函數(shù)。

·??子類的onTransact函數(shù)將業(yè)務(wù)又派發(fā)給其子類來(lái)完成。請(qǐng)讀者務(wù)必注意其中的多層繼承關(guān)系。

通過(guò)這種方式,來(lái)自客戶端的請(qǐng)求就能傳遞到正確的Java Binder對(duì)象了。圖2-3展示AMS響應(yīng)請(qǐng)求的整個(gè)流程。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter2/image003.png" alt="image" />

圖2-3? AMS響應(yīng)請(qǐng)求的流程

圖2-3中,右上角的大方框表示AMS這個(gè)對(duì)象,其間的虛線箭頭表示調(diào)用子類重載的函數(shù)。

2.2.4 ?Java層Binder架構(gòu)總結(jié)


圖2-4展示了Java層的Binder架構(gòu)。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter2/image004.png" alt="image" />

圖 2-4? Java層Binder架構(gòu)

?根據(jù)圖2-4可知:

·??對(duì)于代表客戶端的BinderProxy來(lái)說(shuō),Java層的BinderProxy在Native層對(duì)應(yīng)一個(gè)BpBinder對(duì)象。凡是從Java層發(fā)出的請(qǐng)求,首先從Java層的BinderProxy傳遞到Native層的BpBinder,繼而由BpBinder將請(qǐng)求發(fā)送到Binder驅(qū)動(dòng)。

·??對(duì)于代表服務(wù)端的Service來(lái)說(shuō),Java層的Binder在Native層有一個(gè)JavaBBinder對(duì)象。前面介紹過(guò),所有Java層的Binder在Native層都對(duì)應(yīng)為JavaBBinder,而JavaBBinder僅起到中轉(zhuǎn)作用,即把來(lái)自客戶端的請(qǐng)求從Native層傳遞到Java層。

·??系統(tǒng)中依然只有一個(gè)Native的ServiceManager。

至此,Java層的Binder架構(gòu)已介紹完畢。從前面的分析可以看出,Java層Binder非常依賴Native層的Binder。建議想進(jìn)一步了解Binder的讀者們,要深入了解這一問(wèn)題,有必要閱讀卷I的第6章“深入理解Binder”。

2.3? 心系兩界的MessageQueue

卷I第5章介紹過(guò),MessageQueue類封裝了與消息隊(duì)列有關(guān)的操作。在一個(gè)以消息驅(qū)動(dòng)的系統(tǒng)中,最重要的兩部分就是消息隊(duì)列和消息處理循環(huán)。在Andrid 2.3以前,只有Java世界的居民有資格向MessageQueue中添加消息以驅(qū)動(dòng)Java世界的正常運(yùn)轉(zhuǎn),但從Android 2.3開始,MessageQueue的核心部分下移至Native層,讓Native世界的居民也能利用消息循環(huán)來(lái)處理他們所在世界的事情。因此現(xiàn)在的MessageQueue心系Native和Java兩個(gè)世界。

2.3.1? MessageQueue的創(chuàng)建

現(xiàn)在來(lái)分析MessageQueue是如何跨界工作的,其代碼如下:

[-->MessageQueue.java]

?MessageQueue() {

???????nativeInit(); //構(gòu)造函數(shù)調(diào)用nativeInit,該函數(shù)由Native層實(shí)現(xiàn)

?}

nativeInit函數(shù)的真正實(shí)現(xiàn)為android_os_MessageQueue_nativeInit,其代碼如下:

[-->android_os_MessageQueue.cpp]

static voidandroid_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {

?? //NativeMessageQueue是MessageQueue在Native層的代表

?? NativeMessageQueue*nativeMessageQueue = new NativeMessageQueue();

?? ......

?? //將這個(gè)NativeMessageQueue對(duì)象設(shè)置到Java層保存

?? android_os_MessageQueue_setNativeMessageQueue(env,obj,

?????????????????????????????????????????????????????????nativeMessageQueue);

}

?nativeInit函數(shù)在Native層創(chuàng)建了一個(gè)與MessageQueue對(duì)應(yīng)的NativeMessageQueue對(duì)象,其構(gòu)造函數(shù)如下:

[-->android_os_MessageQueue.cpp]

NativeMessageQueue::NativeMessageQueue() {

?/*

?? 代表消息循環(huán)的Looper也在Native層中呈現(xiàn)身影了。根據(jù)消息驅(qū)動(dòng)的知識(shí),一個(gè)線程會(huì)有一個(gè)

?? Looper來(lái)循環(huán)處理消息隊(duì)列中的消息。下面一行的調(diào)用就是取得保存在線程本地存儲(chǔ)空間

?? (Thread Local Storage)中的Looper對(duì)象

?? */

??? mLooper= Looper::getForThread();

?? if(mLooper == NULL) {

??? /*

???? 如為第一次進(jìn)來(lái),則該線程沒(méi)有設(shè)置本地存儲(chǔ),所以須先創(chuàng)建一個(gè)Looper,然后再將其保存到

???? TLS中,這是很常見(jiàn)的一種以線程為單位的單例模式

???? */

?????mLooper = new Looper(false);

?????Looper::setForThread(mLooper);

??? }

}

Native的Looper是Native世界中參與消息循環(huán)的一位重要角色。雖然它的類名和Java層的Looper類一樣,但此二者其實(shí)并無(wú)任何關(guān)系。這一點(diǎn)以后還將詳細(xì)分析。

2.3.2 ?提取消息

當(dāng)一切準(zhǔn)備就緒后,Java層的消息循環(huán)處理,也就是Looper會(huì)在一個(gè)循環(huán)中提取并處理消息。消息的提取就是調(diào)用MessageQueue的next函數(shù)。當(dāng)消息隊(duì)列為空時(shí),next就會(huì)阻塞。MessageQueue同時(shí)支持Java層和Native層的事件,那么其next函數(shù)該怎么實(shí)現(xiàn)呢?具體代碼如下:

[-->MessagQueue.java]

final Message next() {

??????? intpendingIdleHandlerCount = -1;

??????? intnextPollTimeoutMillis = 0;

?

??????? for(;;) {

?????????? ......

??????????? //mPtr保存了NativeMessageQueue的指針,調(diào)用nativePollOnce進(jìn)行等待

???????????nativePollOnce(mPtr, nextPollTimeoutMillis);

???????????synchronized (this) {

???????????????final long now = SystemClock.uptimeMillis();

???????????????//mMessages用來(lái)存儲(chǔ)消息,這里從其中取一個(gè)消息進(jìn)行處理

???????????????final Message msg = mMessages;

???????????????if (msg != null) {

???????????????????final long when = msg.when;

???????????????????if (now >= when) {

??????????????????????? mBlocked = false;

??????????????????????? mMessages = msg.next;

??????????????????????? msg.next = null;

??????????????????????? msg.markInUse();

??????????????????????? return msg; //返回一個(gè)Message給Looper進(jìn)行派發(fā)和處理

???????????????????} else {

??????????????????????? nextPollTimeoutMillis =(int) Math.min(when - now,

?????????????????????????????????????????????????????Integer.MAX_VALUE);

???????????????????}

???????????????} else {

???????????????????nextPollTimeoutMillis = -1;

???????????????}

?????????? ......

?????????? /*

?????????? 處理注冊(cè)的IdleHandler,當(dāng)MessageQueue中沒(méi)有Message時(shí),

???????????Looper會(huì)調(diào)用IdleHandler做一些工作,例如做垃圾回收等

???????????*/

???????????......

???????????pendingIdleHandlerCount = 0;

??????????nextPollTimeoutMillis = 0;

??????? }

}

看到這里,可能會(huì)有人覺(jué)得這個(gè)MessageQueue很簡(jiǎn)單,不就是從以前在Java層的wait變成現(xiàn)在Native層的wait了嗎?但是事情本質(zhì)比表象要復(fù)雜得多,來(lái)思考下面的情況:

·??nativePollOnce返回后,next函數(shù)將從mMessages中提取一個(gè)消息。也就是說(shuō),要讓nativePollOnce返回,至少要添加一個(gè)消息到消息隊(duì)列,否則nativePollOnce不過(guò)是做了一次無(wú)用功罷了。

·??如果nativePollOnce將在Native層等待,就表明Native層也可以投遞Message,但是從Message類的實(shí)現(xiàn)代碼上看,該類和Native層沒(méi)有建立任何關(guān)系。那么nativePollOnce在等待什么呢?

對(duì)于上面的問(wèn)題,相信有些讀者心中已有了答案:nativePollOnce不僅在等待Java層來(lái)的Message,實(shí)際上還在Native還做了大量的工作。

下面我們來(lái)分析Java層投遞Message并觸發(fā)nativePollOnce工作的正常流程。

1. ?在Java層投遞Message

MessageQueue的enqueueMessage函數(shù)完成將一個(gè)Message投遞到MessageQueue中的工作,其代碼如下:

[-->MesssageQueue.java]

final boolean enqueueMessage(Message msg, longwhen) {

?????? ?......

???????final boolean needWake;

???????synchronized (this) {

???????????if (mQuiting) {

???????????????return false;

???????????} else if (msg.target == null) {

???????????????mQuiting = true;

???????????}

???????????msg.when = when;

???????????Message p = mMessages;

???????????if (p == null || when == 0 || when < p.when) {

???????????????/*

????????????????如果p為空,表明消息隊(duì)列中沒(méi)有消息,那么msg將是第一個(gè)消息,needWake

????????????????需要根據(jù)mBlocked的情況考慮是否觸發(fā)

???????????????*/

???????????????msg.next = p;

???????????????mMessages = msg;

???????????????needWake = mBlocked;

???????????} else {

???????????????//如果p不為空,表明消息隊(duì)列中還有剩余消息,需要將新的msg加到消息尾

???????????????Message prev = null;

???????????????while (p != null && p.when <= when) {

???????????????????prev = p;

???????????????????p = p.next;

???????????????}

???????????????msg.next = prev.next;

???????????????prev.next = msg;

???????????????//因?yàn)橄㈥?duì)列之前還剩余有消息,所以這里不用調(diào)用nativeWakeup

???????????????needWake = false;

???????????}

??????? }

??????? if(needWake) {

???????????//調(diào)用nativeWake,以觸發(fā)nativePollOnce函數(shù)結(jié)束等待

???????????nativeWake(mPtr);

???? ???}

???????return true;

??? }

上面的代碼比較簡(jiǎn)單,主要功能是:

·??將message按執(zhí)行時(shí)間排序,并加入消息隊(duì)。

·??根據(jù)情況調(diào)用nativeWake函數(shù),以觸發(fā)nativePollOnce函數(shù),結(jié)束等待。

建議 雖然代碼簡(jiǎn)單,但是對(duì)于那些不熟悉多線程的讀者,還是要細(xì)細(xì)品味一下mBlocked值的作用。我們常說(shuō)細(xì)節(jié)體現(xiàn)美,代碼也一樣,這個(gè)小小的mBlocked正是如此。

2.? nativeWake函數(shù)分析

nativeWake函數(shù)的代碼如下所示:

[-->android_os_MessageQueue.cpp]

static voidandroid_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj,

??????????????????????????????????????????????????????jint ptr)

{

??? NativeMessageQueue*nativeMessageQueue =? //取出NativeMessageQueue對(duì)象

????????????????????? ?reinterpret_cast<NativeMessageQueue*>(ptr);

??? returnnativeMessageQueue->wake(); //調(diào)用它的wake函