《深入理解Android:卷III A》一一2.2Java层中的Binder分析

2.2Java层中的Binder分析

2.2.1Binder架构总览
如果读者读过卷I的第6章,相信就不会对Binder架构中代表Client的Bp端及代表Server的Bn端感到陌生。Java层中Binder实际上也是一个C/S架构,而且其在类的命名上尽量保持与Native层一致,因此可认为,Java层的Binder架构是Native层Binder架构的一个镜像。Java层的Binder架构中的成员如图2-1所示。
由图2-1可知:


图 2-1Java层中的Binder家族
系统定义了一个IBinder接口类以及DeathRecepient接口。
Binder类和BinderProxy类分别实现了IBinder接口。其中Binder类作为服务端的Bn的代表,而BinderProxy作为客户端的Bp的代表。
系统中还定义了一个BinderInternal类。该类是一个仅供Binder框架使用的类。它内部有一个GcWatcher类,该类专门用于处理和Binder相关的垃圾回收。
Java层同样提供一个用于承载通信数据的Parcel类。
IBinder接口类中定义了一个叫FLAG_ONEWAY的整型变量,该变量的意义非常重要。当客户端利用Binder机制发起一个跨进程的函数调用时,调用方(即客户端)一般会阻塞,直到服务端返回结果。这种方式和普通的函数调用是一样的。但是在调用Binder函数时,在指明了FLAG_ONEWAY标志后,调用方只要把请求发送到Binder驱动即可返回,而不用等待服务端的结果,这就是一种所谓的非阻塞方式。在Native层中,涉及的Binder调用基本都是阻塞的,但是在Java层的framework中,使用FLAG_ONEWAY进行Binder调用的情况非常多,以后经常会碰到。
使用FLAG_ONEWAY进行函数调用的程序在设计上有什么特点?这里简单分析一下:对使用FLAG_ONEWAY的函数来说,客户端仅向服务端发出请求,但是并不能确定服务端是否处理了该请求。所以,客户端一般会向服务端注册一个回调(同样是跨进程的Binder调用),一旦服务端处理了该请求,就会调用此回调来通知客户端处理结果。当然,这种回调函数也大多采用FLAG_ONEWAY的方式。
2.2.2初始化Java层Binder框架
虽然Java层Binder系统是Native层Binder系统的一个镜像,但这个镜像终归还需借助Native层Binder系统来开展工作,即镜像和Native层Binder有着千丝万缕的关系,一定要在Java层Binder正式工作之前建立这种关系。下面分析Java层Binder框架是如何初始化的。
在Android系统中,在Java初创时期,系统会提前注册一些JNI函数,其中有一个函数专门负责搭建Java Binder和Native Binder交互关系,该函数是register_android_os_Binder,代码如下:
[android_util_Binder.cpp-->register_android_os_Binder()]
int register_android_os_Binder(JNIEnv* env)
{
// 初始化Java Binder类和Native层的关系
if (int_register_android_os_Binder(env) < 0)
return -1;
// 初始化Java BinderInternal类和Native层的关系
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
// 初始化Java BinderProxy类和Native层的关系
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
......
return 0;
}
据上面的代码可知,register_android_os_Binder函数完成了Java Binder架构中最重要的三个类的初始化工作。
1. Binder类的初始化
int_register_android_os_Binder函数完成了Binder类的初始化工作,代码如下:
[android_util_Binder.cpp-->int_register_android_os_Binder()]
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz;
//kBinderPathName为Java层中Binder类的全路径名,“android/os/Binder“
clazz = env->FindClass(kBinderPathName);
/* gBinderOffSets是一个静态类对象,它专门保存Binder类的一些在JNI层中使用的信息,
如成员函数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");
// 注册Binder类中native函数的实现
return AndroidRuntime::registerNativeMethods(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
由上面代码可知,gBinderOffsets对象保存了和Binder类相关的某些在JNI层中使用的信息。它们将用来在JNI层对Java层的Binder对象进行操作。execTransact()函数以及mObject成员的用途将在2.2.3节介绍。
如果读者对JNI不是很清楚,可参阅卷I第2章“深入理解JNI”。
2. BinderInternal类的初始化
下一个初始化的类是BinderInternal,其代码在int_register_android_os_BinderInternal函数中。
[android_util_Binder.cpp-->int_register_android_os_BinderInternal()]
static int int_register_android_os_BinderInternal(JNIEnv
env)
{
jclass clazz;
// 根据BinderInternal的全路径名找到代表该类的jclass对象。全路径名为
// “com/android/internal/os/BinderInternal”
clazz = env->FindClass(kBinderInternalPathName);
//gBinderInternalOffsets也是一个静态对象,用来保存BinderInternal类的一些信息
gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
// 获取forceBinderGc的methodID
gBinderInternalOffsets.mForceGc
= env->GetStaticMethodID(clazz, "forceBinderGc", "()V");
// 注册BinderInternal类中native函数的实现
return AndroidRuntime::registerNativeMethods(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
int_register_android_os_BinderInternal的工作内容和int_register_android_os_Binder的工作内容类似:
获取一些有用的methodID和fieldID。这表明JNI层一定会向上调用Java层的函数。
注册相关类中native函数的实现。
3. BinderProxy类的初始化
int_register_android_os_BinderProxy完成了BinderProxy类的初始化工作,代码稍显复杂,如下所示:
[android_util_Binder.cpp -->int_register_android_os_BinderProxy()]
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
jclass clazz;

// ① gWeakReferenceOffsets用来和WeakReference类打交道
clazz = env->FindClass("java/lang/ref/WeakReference");
gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
// 获取WeakReference类get函数的MethodID
gWeakReferenceOffsets.mGet= env->GetMethodID(clazz, "get",
                                "()Ljava/lang/Object;");

// ② gErrorOffsets用来和Error类打交道
clazz = env->FindClass("java/lang/Error");
gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);

// ③ gBinderProxyOffsets用来和BinderProxy类打交道
clazz = env->FindClass(kBinderProxyPathName);
gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderProxyOffsets.mConstructor= env->GetMethodID(clazz, "<init>", "()V");
...... //获取BinderProxy的一些信息

// ④ gClassOffsets用来和Class类打交道
clazz = env->FindClass("java/lang/Class");
gClassOffsets.mGetName =env->GetMethodID(clazz,
                       "getName", "()Ljava/lang/String;");

// 注册BinderProxy native函数的实现
return AndroidRuntime::registerNativeMethods(env,
      kBinderProxyPathName,gBinderProxyMethods,
                            NELEM(gBinderProxyMethods));

}
据上面代码可知,int_register_android_os_BinderProxy函数除了初始化BinderProxy类外,还获取了WeakReference类和Error类的一些信息。看来BinderProxy对象的生命周期会委托WeakReference来管理,所以JNI层会获取该类get函数的MethodID。
至此,Java Binder几个重要成员的初始化已完成,同时在代码中定义了几个全局静态对象,分别是gBinderOffsets、gBinderInternalOffsets和gBinderProxyOffsets。
框架的初始化其实就是提前获取一些JNI层的使用信息,如类成员函数的MethodID、类成员变量的fieldID等。这项工作是必需的,因为它能节省每次使用时获取这些信息的时间。当Binder调用频繁时,这些时间累积起来还是不容小觑的。
另外,这个过程中所创建的几个全局静态对象为JNI层访问Java层的对象提供了依据。而在每个初始化函数中所执行的registerNativeMethods()方法则为Java层访问JNI层打通了道路。换句话说,Binder初始化的工作就是通过JNI建立起Native Binder与Java Binder之间互相通信的桥梁。
下面通过一个例子来分析Java Binder的工作流程。
2.2.3窥一斑,可见全豹乎
这个例子源自ActivityManagerService,我们试图通过它揭示Java层Binder的工作原理。先来描述一下该例子的分析步骤:
首先分析AMS如何将自己注册到ServiceManager。
然后分析AMS如何响应客户端的Binder调用请求。
本例的起点是setSystemProcess,其代码如下所示:
[ActivityManagerService.java-->ActivityManagerService.setSystemProcess()]
public static void setSystemProcess() {
try {
ActivityManagerService m = mSelf;
// 将ActivityManagerService服务注册到ServiceManager中
ServiceManager.addService("activity", m);......
} catch { ... }
return;
}
上面所示代码行的目的是将ActivityManagerService服务(以后简称AMS)加到ServiceManager中。
在整个Android系统中有一个Native的ServiceManager(以后简称SM)进程,它统筹管理Android系统上的所有服务。成为一个服务的首要条件是先在SM中注册。下面来看Java层的服务是如何向SM注册的。
1. 向ServiceManager注册服务
(1)创建ServiceManagerProxy
向SM注册服务的函数叫addService,其代码如下:
[ServiceManager.java-->ServiceManager.addService()]
public static void addService(String name, IBinder service) {
try {
// getIServiceManager返回什么
getIServiceManager().addService(name, service);
}
......
}
首先需要搞清楚getIServiceManager()方法返回的是一个什么对象?参考其实现:
[ServiceManager.java-->ServiceManager.getIServiceManager()]
private static IServiceManager getIServiceManager() {
......
// 调用asInterface,传递的参数类型为IBinder
sServiceManager = ServiceManagerNative.asInterface(
BinderInternal.getContextObject());
return sServiceManager;
}
asInterface()方法的参数为BinderInternal.getContextObject()的返回值。于是这个简短的方法中有两个内容值得讨论:BinderInternal.getContextObject()以及asInterface()。
BinderInternal.getContextObject()方法是一个native函数,参考其实现:
[android_util_Binder.cpp-->android_os_BinderInternal_getContextObject()]
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
/* 下面这句代码在卷I第6章详细分析过,它将返回一个BpProxy对象,其中
NULL(即0,用于标识目的端)指定Proxy通信的目的端是ServiceManager /
sp b = ProcessState::self()->getContextObject(NULL);
// 由Native对象创建一个Java对象,下面分析该函数
return javaObjectForIBinder(env, b);
}
可见,Java层的ServiceManager需要在Native层获取指向Native进程中ServiceManager的BpProxy。这个BpProxy不能由Java层的ServiceManager直接使用,于是android_os_BinderInteral_getContextObject()函数通过javaObjectForIBinder()函数将创建一个封装了这个BpProxy的一个Java对象并返回给调用者。ServiceManager便可以通过这个Java对象实现对BpProxy的访问。参考这个Java对象的创建过程:
[android_util_Binder.cpp-->javaObjectForIBinder()]
jobject javaObjectForIBinder(JNIEnv
env, const sp& val)
{
// mProxyLock是一个全局静态CMutex对象
AutoMutex _l(mProxyLock);

/* val对象实际类型是BpBinder,读者可自行分析BpBinder.cpp中的findObject函数。
   事实上,在Native层的BpBinder中有一个ObjectManager,它用来管理在Native BpBinder上
   创建的Java BpBinder对象。下面这个findObject用来判断gBinderProxyOffsets是否已经
   保存在ObjectManager中。如果是,那就需要删除这个旧的对象*/
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);
}

// ① 创建一个新的BinderProxy对象,并将它注册到Native BpBinder对象的ObjectManager中
object = env->NewObject(gBinderProxyOffsets.mClass,
                    gBinderProxyOffsets.mConstructor);
if (object != NULL) {
    /* ② 把Native层的BpProxy的指针保存到BinderProxy对象的成员字段mObject中。
       于是BinderProxy对象的Native方法可以通过mObject获取BpProxy对象的指针。
       这个操作是将BinderProxy与BpProxy联系起来的纽带 */
    env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());
    val->incStrong(object);
    jobject refObject = env->NewGlobalRef(
         env->GetObjectField(object, gBinderProxyOffsets.mSelf));

    /* 将这个新创建的BinderProxy对象注册(attach)到BpBinder的ObjectManager中,同时
       注册一个回收函数proxy_cleanup。当BinderProxy对象撤销(detach)的时候,该函数会
       被调用,以释放一些资源。读者可自行研究proxy_cleanup函数*/
    val->attachObject(&gBinderProxyOffsets, refObject,
                      jnienv_to_javavm(env), proxy_cleanup);

    // DeathRecipientList保存了一个用于死亡通知的list
    sp<DeathRecipientList> drl = new DeathRecipientList;
    drl->incStrong((void*)javaObjectForIBinder);
    //将死亡通知list和BinderProxy对象联系起来
    env->SetIntField(object, gBinderProxyOffsets.mOrgue,
                         reinterpret_cast<jint>(drl.get()));

    // 增加该Proxy对象的引用计数
    android_atomic_inc(&gNumProxyRefs);
    /* 下面这个函数用于垃圾回收。创建的Proxy对象一旦超过200个,该函数将调用BinderInter
       类的ForceGc做一次垃圾回收 */
    incRefsCreated(env);
}
return object;

}
BinderInternal.getContextObject的代码有点多,简单整理一下,可知该函数完成了以下两个工作:
创建了一个Java层的BinderProxy对象。
通过JNI,该BinderProxy对象和一个Native的BpProxy对象挂钩,而该BpProxy对象的通信目标就是ServiceManager。
接下来讨论asInterface()方法,大家还记得在Native层Binder中那个著名的interface_cast宏吗?在Java层中,虽然没有这样的宏,但是定义了一个类似的函数asInterface。下面来分析ServiceManagerNative类的asInterface函数,其代码如下:
[ServiceManagerNative.java-->ServiceManagerNative.asInterface()]
static public IServiceManager asInterface(IBinder obj)
{
...... // 以obj为参数,创建一个ServiceManagerProxy对象
return new ServiceManagerProxy(obj);
}
上面代码和Native层interface_cast宏非常类似,都是以一个BpProxy对象为参数构造一个和业务相关的Proxy对象,例如这里的ServiceManagerProxy对象。ServiceManagerProxy对象的各个业务函数会将相应请求打包后交给BpProxy对象,最终由BpProxy对象发送给Binder驱动以完成一次通信。
实际上BpProxy也不会直接和Binder驱动交互,真正和Binder驱动交互的是IPCThreadState。
(2)addService函数分析
现在来分析ServiceManagerProxy的addService函数,其代码如下:
[ServcieManagerNative.java-->ServiceManagerProxy.addService()]
public void addService(String name, IBinder service)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
// 注意下面这个writeStrongBinder函数,后面我们会详细分析它
data.writeStrongBinder(service);
/* mRemote实际上就是BinderProxy对象,调用它的transact,将封装好的请求数据发送出去 /
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
BinderProxy的transact是一个native函数,其实现函数的代码如下所示:
[android_util_Binder.cpp-->android_os_BinderProxy_transact()]
static jboolean android_os_BinderProxy_transact(JNIEnv
env, jobject obj,
jint code, jobject dataObj,
jobject replyObj, jint flags)
{
......
// 从Java的Parcel对象中得到作为参数的Native的Parcel对象
Parcel* data = parcelForJavaObject(env, dataObj);
if (data == NULL) {
return JNI_FALSE;
}
// 得到一个用于接收回复的Parcel对象
Parcel* reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
}

// 从Java的BinderProxy对象中得到之前已经创建好的那个Native的BpBinder对象
IBinder target = (IBinder)
    env->GetIntField(obj, gBinderProxyOffsets.mObject);
......
// 通过Native的BpBinder对象将请求发送给ServiceManager
status_t err = target->transact(code, *data, reply, flags);
......
signalExceptionForError(env, obj, err);
return JNI_FALSE;

}
看了上面的代码你会发现,Java层的Binder最终还是要借助Native的Binder进行通信的。
从架构的角度看,在Java中搭建了一整套框架,如IBinder接口、Binder类和BinderProxy类。但是从通信角度看,不论架构的编写采用的是Native语言还是Java语言,只要把请求传递到Binder驱动就可以了,所以通信的目的是向binder发送请求和接收回复。在这个目的之上,考虑到软件的灵活性和可扩展性,于是编写了一个架构。反过来说,也可以不使用架构(即没有使用任何接口、派生之类的东西)而直接和binder交互,例如ServiceManager作为Binder的一个核心程序,就是直接读取/dev/binder设备,获取并处理请求。从这一点上看,Binder的目的虽然简单(即打开binder设备,然后读请求和写回复),但是架构复杂(编写各种接口类和封装类等)。我们在研究源码时,一定要先搞清楚目的。实现只不过是达到该目的的一种手段和方式。脱离目的的实现,如缘木求鱼,很容易偏离事物本质。
在对addService进行分析时曾提示writeStrongBinder是一个特别的函数。那么它特别在哪里呢?下面将给出解释。
(3)三人行之Binder、JavaBBinderHolder和JavaBBinder
ActivityManagerService从ActivityManagerNative类派生,并实现了一些接口,其中和Binder相关的只有这个ActivityManagerNative类,其原型如下:
[ActivityManagerNative.java-->ActivityManagerNative]
public abstract class ActivityManagerNative
extends Binder
implements IActivityManager
ActivityManagerNative从Binder派生,并实现了IActivityManager接口。下面来看ActivityManagerNative的构造函数:
[ActivityManagerNative.java-->ActivityManagerNative.ActivityManagerNative()]
public ActivityManagerNative() {
attachInterface(this, descriptor);// 该函数很简单,读者可自行分析
}
而ActivityManagerNative父类的构造函数则是Binder的构造函数:
[Binder.java-->Binder.Binder()]
public Binder() {
init();
}
Binder构造函数会调用native的init函数,其实现的代码如下:
[android_util_Binder.cpp-->android_os_Binder_init()]
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
// 创建一个JavaBBinderHolder对象
JavaBBinderHolder* jbh = new JavaBBinderHolder();
bh->incStrong((void*)android_os_Binder_init);
// 将这个JavaBBinderHolder对象保存到Java Binder对象的mObject成员中
env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
}
从上面代码可知,Java的Binder对象将和一个Native的JavaBBinderHolder对象相关联。那么,JavaBBinderHolder是何方神圣呢?其定义如下:
[android_util_Binder.cpp-->JavaBBinderHolder]
class JavaBBinderHolder : public RefBase
{
public:
sp get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp b = mBinder.promote();
if (b == NULL) {
// 创建一个JavaBBinder,obj实际上是Java层中的Binder对象
b = new JavaBBinder(env, obj);
mBinder = b;
}
return b;
}
......
private:
Mutex mLock;
wp mBinder;
};
从派生关系上可以发现,JavaBBinderHolder仅从RefBase派生,所以它不属于Binder家族。Java层的Binder对象为什么会和Native层的一个与Binder家族无关的对象绑定呢?仔细观察JavaBBinderHolder的定义可知:JavaBBinderHolder类的get函数中创建了一个JavaBBinder对象,这个对象就是从BnBinder派生的。
那么,这个get函数是在哪里调用的?答案在下面这句代码中:
//其中,data是Parcel对象,service此时还是ActivityManagerService
data.writeStrongBinder(service);
writeStrongBinder会做一个替换工作,下面是它的native代码实现:
[android_util_Binder.cpp-->android_os_Parcel_writeStrongBinder()]
static void android_os_Parcel_writeStrongBinder(JNIEnv* env,
jobject clazz, jobject object)
{
/* parcel是一个Native的对象,writeStrongBinder的真正参数是
ibinderForJavaObject()的返回值 /
const status_t err = parcel->writeStrongBinder(
ibinderForJavaObject(env, object));
}
[android_util_Binder.cpp-->ibinderForJavaObject()]
sp ibinderForJavaObject(JNIEnv
env, jobject obj)
{
/* 如果Java的obj是Binder类,则首先获得JavaBBinderHolder对象,然后调用它的get()函数。
而这个get将返回一个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对象
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
    return (IBinder*)
        env->GetIntField(obj, gBinderProxyOffsets.mObject);
}

return NULL;
}
根据上面的介绍会发现,addService实际添加到Parcel的并不是AMS本身,而是一个叫JavaBBinder的对象。而最终传递到Binder驱动的正是这个JavaBBinder对象。
读者此时容易想到,Java层中所有的Binder对应的都是这个JavaBBinder。当然,不同的Binder对象对应不同的JavaBBinder对象。
图2-2展示了Java Binder、JavaBBinderHolder和JavaBBinder的关系。
从图2-2可知:
Java层的Binder通过mObject指向一个Native层的JavaBBinderHolder对象。
Native层的JavaBBinderHolder对象通过mBinder成员变量指向一个Native的JavaBBinder对象。
Native的JavaBBinder对象又通过mObject变量指向一个Java层的Binder对象。
为什么不直接让Java层的Binder对象指向Native层的JavaBBinder对象呢?由于缺乏设计文档,这里不便妄加揣测,但从JavaBBinderHolder的实现上来分析,估计和垃圾回收(内存管理)有关,因为JavaBBinderHolder中的mBinder对象的类型被定义成弱引用wp了。
对此有更好的解释的读者,不妨与大家分享一下。
2. ActivityManagerService响应请求
初见JavaBBinde时,多少有些吃惊。回想一下Native层的Binder架构:虽然在代码中调用的是Binder类提供的接口,但其对象却是一个实际的服务端对象,例如MediaPlayerService对象、AudioFlinger对象。
而在Java层的Binder架构中,JavaBBinder却是一个和业务完全无关的对象。那么,这个对象如何实现不同业务呢?
为回答此问题,我们必须查看它的onTransact函数。当收到请求时,系统会调用这个函数。
关于这个问题,建议读者阅读卷I第6章“深入理解Binder”。
[android_util_Binder.cpp-->JavaBBinder::onTransact()]
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();
.......
// 调用Java层Binder对象的execTranscat函数
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,现在调用它的exec-Transact()方法,该方法在Binder类中实现,具体代码如下:
[Binder.java-->Binder.execTransact()]
private boolean execTransact(int code, int dataObj, int replyObj,int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
boolean res;
try {
//调用onTransact函数,派生类可以重新实现这个函数,以完成业务功能
res = onTransact(code, data, reply, flags);
} catch { ... }
reply.recycle();
data.recycle();
return res;
}
ActivityManagerNative类实现了onTransact函数,代码如下:
[ActivityManagerNative.java-->ActivityManagerNative.onTransact()]
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
......
//再由ActivityManagerService实现业务函数startActivity
int result = startActivity(app, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, profileFile,
profileFd, autoStopProfiler);
reply.writeNoException();
reply.writeInt(result);
return true;
}
.... // 处理其他请求的情况
}
}
由此可以看出,JavaBBinder仅是一个传声筒,它本身不实现任何业务函数,其工作是:
当它收到请求时,只是简单地调用它所绑定的Java层Binder对象的exeTransact。
该Binder对象的exeTransact调用其子类实现的onTransact函数。
子类的onTransact函数将业务又派发给其子类来完成。请读者务必注意其中的多层继承关系。
通过这种方式,来自客户端的请求就能传递到正确的Java Binder对象了。图2-3展示AMS响应请求的整个流程。
在图2-3中,右上角的大方框表示AMS对象,其中的虚线箭头表示调用子类重载的函数。

图2-3 AMS响应请求的流程
2.2.4理解AIDL
经过上一节的介绍,你已经明白在Java层Binder的架构中,Bp端可以通过BinderProxy的transact()方法与Bn端发送请求,而Bn端通过继承Binder类重写onTransact()接收并处理来自Bp端的请求。这个结构非常清晰而且简单,但是实现起来却颇为烦琐。于是Android提供了AIDL语言以及AIDL解释器自动生成一个服务的Bn端,即Bp端用于处理Binder通信的代码。
AIDL的语法与定义一个Java接口的语法非常相似。为了避免业务实现对分析的干扰,本节通过一个最简单的例子对AIDL的原理进行介绍。
[IMyServer.aidl]
package com.understanding.samples;
interface IMyServer {
int foo(String str);
}
IMyServer.aidl定义了一个名为IMyServer的Binder服务,并提供了一个可以跨Binder调用的接口foo()。可以通过aidl工具将其解析为一个实现了Bn端及Bp端通过Binder进行通信的Java源代码。具体命令如下:
aidl com/understanding/samples/IMyServer.aidl
生成的IMyServer.java可以在com/understanding/samples/文件夹下找到。
读者可以阅读aidl有关的文档了解此工具的详细功能。
[IMyServer.java-->IMyServer]
package com.understanding.samples;
/* ① 首先,IMyServer.aidl被解析为一个Java接口IMyServer。这个接口定义了AIDL文件中所定义
的接口foo() /
public interface IMyServer extends android.os.IInterface {
/
② aidl工具生成了一个继承自IMyServer接口的抽象类IMyServer.Stub。这个抽象类实现了Bn
端通过onTransact()方法接收来自Bp端的请求的代码。本例中的foo()方法在这个类中会被定义
成一个抽象方法。因为aidl工具根本不知道foo()方法是做什么的,它只能在onTransact()中得知Bp端希
望对foo()方法进行调用,所以Stub类是抽象的 /
public static abstract class Stub extends android.os.Binder implements
com.understanding.samples.IMyServer {
...... // Stub类的其他实现
/
onTransact()根据code的值选择调用IMyServer接口中的不同方法。本例中
TRANSACTION_foo意味着需要通过调用foo()方法完成请求 */
public boolean onTransact(int code, android.os.Parcel data,
android.os.Parcel reply, int flags)
throws android.os.RemoteException {
switch (code) {
......
case TRANSACTION_foo: {
...... // 从data中读取参数_arg0
// Stub类的子类需要实现foo()方法
int _result = this.foo(_arg0);
...... // 向reply中写入_result
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

    /* ③ aidl工具还生成了一个继承自IMyServer接口的类Proxy,它是Bp端的实现。与Bn端的Stub
      类不同,它实现了foo()函数。因为foo()函数在Bp端的实现是确定的,即将参数存储到Parcel
      中,然后执行transact()方法将请求发送给Bn端,然后从reply中读取返回值并返回给调
      用者 */
    private static class Proxy implements com.understanding.samples.IMyServer {
        ...... // Proxy类的其他实现
        public int foo(java.lang.String str)
                throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            int _result;
            try {
                ...... // 将参数str写入参数_data
                // mRemote就是指向IMyServer Bn端的BinderProxy
                mRemote.transact(Stub.TRANSACTION_foo, _data, _reply, 0);
                ......// 从_replay中读取返回值_result
            } finally { ...... }
            return _result;
        }
    }

    // TRANSACTION_foo常量用于定义foo()方法的code
        static final int TRANSACTION_foo =
                         (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
// 声明IMyServer所提供的接口
public int foo(java.lang.String str) throws android.os.RemoteException;

}
可见一个AIDL文件被aidl工具解析之后会有三个产物:
IMyServer接口。它仅仅用来在Java中声明IMyServer.aidl中所声明的接口。
IMyServer.Stub类。这个继承自Binder类的抽象类实现了Bn端与Binder通信相关的代码。
IMyServer.Stub.Proxy类。这个类实现了Bp端与Binder通信相关的代码。
在完成aidl的解析之后,为了实现一个Bn端,开发者需要继承IMyServer.Stub类并实现其抽象方法。如下所示:
class MyServer extends IMyServer.Stub {
int foo(String str) {
// 做点什么都可以
return str.length();
}
}
于是每一个MyServer类的实例,都具有了作为Bn端的能力。典型的做法是将MyServer类的实例通过ServiceManager.addService()将其注册为一个系统服务,或者在一个Android标准Service的onBind()方法中将其作为返回值使之可以被其他进程访问。另外,也可以通过Binder调用将其传递给另外一个进程,使之成为一个跨进程的回调对象。
那么Bp端将如何使用IMyServer.Proxy呢?在Bp端所在进程中,一旦获取了IMyServer的BinderProxy(通过ServiceManager.getService()、onServiceConnected()或者其他方式),就可以通过如下方式获得一个IMyServer.Proxy:
// 其中binderProxy就是通过ServiceManager.getService()获取的
IMyServer remote = IMyServer.Stub.asInterface(binderProxy);
remote.foo(“Hello AIDL!”);
IMyServer.Stub.asInterface()的实现如下:
[IMyServer.java-->IMyServer.Stub.asInterface()]
public static com.understanding.samples.IMyServer asInterface(
android.os.IBinder obj) {
......
// 创建一个IMyServer.Stub.Proxy,其中参数obj将会被保存为Proxy类的mRemote成员
return new com.understanding.samples.IMyServer.Stub.Proxy(obj);
}
可见,AIDL使得构建一个Binder服务的工作大大简化了。
2.2.5Java层Binder架构总结
图2-4展示了Java层的Binder架构。
根据图2-4可知:
对代表客户端的BinderProxy来说,Java层的BinderProxy在Native层对应一个BpBinder对象。凡是从Java层发出的请求,首先从Java层的BinderProxy传递到Native层的BpBinder,继而由BpBinder将请求发送到Binder驱动。
对代表服务端的Service来说,Java层的Binder在Native层有一个JavaBBinder对象。前面介绍过,所有Java层的Binder在Native层都对应为JavaBBinder,而JavaBBinder仅起到中转作用,即把来自客户端的请求从Native层传递到Java层。
系统中依然只有一个Native的ServiceManager。

图2-4Java层Binder架构
至此,Java层的Binder架构已介绍完毕。从前面的分析可以看出,Java层的Binder非常依赖Native层的Binder。建议想进一步了解Binder的读者要深入了解这一问题,有必要阅读卷I的第6章。

时间: 2024-08-04 02:03:34

《深入理解Android:卷III A》一一2.2Java层中的Binder分析的相关文章

《深入理解Android:卷III A》一一2.1概述

2.1概述 由于本书所介绍的内容是以Java层的系统服务为主,因此Binder相关的应用在本书中比比皆是.而MessageQueue作为Android中重要的任务调度工具,它的使用也是随处可见.所以本书有必要对这两个工具有所介绍.根据邓凡平的同意与推荐,本章由卷II第2章升级到4.2.2,并且增加了对AIDL相关知识点的分析.本章作为本书Android源代码分析之旅的开篇,将重点关注两个基础知识点,它们是:Binder系统在Java世界是如何布局和工作的.MessageQueue的新职责.先来分

深入理解Android中View和ViewGroup

深入理解Android中View 这回我们是深入到View内部,去研究View,去了解View的工作,抛弃其他因素,以便为以后能灵活的使用自定义空间打下一定的基础.希望有志同道合的朋友一起来探讨,深入Android内部,深入理解Android. 一.View是什么? View是什么了,每个人都有自己的理解.在Android的官方文档中是这样描述的:这个类表示了用户界面的基本构建模块.一个View占用了屏幕上的一个矩形区域并且负责界面绘制和事件处理.View是用来构建用户界面组件(Button,T

深入理解Android手势识别_Android

对于触摸屏,其原生的消息无非按下.抬起.移动这几种,我们只需要简单重载onTouch或者设置触摸侦听器setOnTouchListener即可进行处理.不过,为了提高我们的APP的用户体验,有时候我们需要识别用户的手势,Android给我们提供的手势识别工具GestureDetector就可以帮上大忙了. 基础 GestureDetector的工作原理是,当我们接收到用户触摸消息时,将这个消息交给GestureDetector去加工,我们通过设置侦听器获得GestureDetector处理后的手

深入理解Android中的建造者模式_Android

前言 在Android开发过程中,我发现很多安卓源代码里应用了设计模式,比较常用的有适配器模式(各种adapter),建造者模式(Alert Dialog的构建)等等.虽然我们对大多数设计模式都有所了解,但是在应用设计模式的这个方面,感觉很多人在这方面有所不足.所以这篇文章我们一起深入的理解Android中的建造者模式. 建造者模式(Builder Pattern)也叫生成器模式,其定义如下: separate the construction of a complex object from

理解Android中的自定义属性_Android

本文实例讲解了Android中的自定义属性,具体内容如下 1.引言 对于自定义属性,大家肯定都不陌生,遵循以下几步,就可以实现: 自定义一个CustomView(extends View )类 编写values/attrs.xml,在其中编写styleable和item等标签元素 在布局文件中CustomView使用自定义的属性(注意namespace) 在CustomView的构造方法中通过TypedArray获取 ps:如果你对上述几个步骤不熟悉,建议先熟悉下,再继续~ 那么,我有几个问题:

《深入理解Android:卷III A》一一1.4调试Android源代码

1.4调试Android源代码 调试是分析问题与印证对代码的理解的最有效手段,对Android这种复杂而庞大的系统来说尤为如此.Android的源代码主要由Java代码以及C/C++代码构成,因此调试Android源代码需要从Java的调试以及C/C++的调试两个方面说起.1.4.1使用Eclipse调试Android Java源代码 由于Android源代码是以一个普通的Java工程的方式导入的,于是在Eclipse中不能通过ADT所提供的DDMS直接对其进行远程调试. 1)首先需要通过DDM

《深入理解Android:卷III A》一一3.1概述

3.1概述 通过对卷I第7章的学习,相信大家已经对AudioTrack.AudioRecord.音频设备路由等知识有了深入了解.这一章将详细介绍音频系统在Java层的实现,围绕AudioService这个系统服务深入探讨在Android SDK 中看到的音频相关的机制的实现.在分析Android音频系统时,习惯将其实现分为两个部分:数据流和策略.数据流描述了音频数据从数据源流向目的地的过程.而策略则是管理及控制数据流的路径与呈现的过程.在卷I所探讨的Native 层音频系统中,AudioTrac

《深入理解Android:卷III A》一一2.3心系两界的MessageQueue

2.3心系两界的MessageQueue 卷I第5章介绍过,MessageQueue类封装了与消息队列有关的操作.在一个以消息驱动的系统中,最重要的两部分就是消息队列和消息处理循环.在Andrid 2.3以前,只有Java世界的居民有资格向MessageQueue中添加消息以驱动Java世界的正常运转,但从Android 2.3开始,MessageQueue的核心部分下移至Native层,让Native世界的居民也能利用消息循环来处理他们所在世界的事情.因此现在的MessageQueue心系Na

《深入理解Android:Telephony原理剖析与最佳实践》一导读

前 言 随着ICT技术的推广和发展,在三网融合.智慧的地球(物联网)等概念风行的形势下,手机终端技术的发展和进步可谓日新月异:Android经受住了市场的考验,并占据了较大的市场份额,从手机芯片厂家.手机生产厂家到各种应用开发公司.互联网公司等,逐步形成了以Android系统平台为核心的上下游产业链.正是由于Android源代码的开源,各大手机厂商才能通过深度定制Android系统平台,在降低研发成本的同时,快速推出具有自身特色的Android智能手机产品.因此,各大手机厂家在推出新版本Andr