ThinkSSL🔒 一键申购 5分钟快速签发 30天无理由退款 购买更放心 广告
这个例子源自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系统上的所有Service。成为一个Service的首要条件是先在SM中注册。下面来看Java层的Service是如何向SM注册的。 #### 1. 向ServiceManager注册服务 ##### (1)创建ServiceManagerProxy 向SM注册服务的函数叫addService,其代码如下: **ServiceManager.java-->ServiceManager.addService()** ``` public static void addService(String name, IBinderservice) { try { //getIServiceManager返回什么 getIServiceManager().addService(name, service); } ...... } ``` 首先需要搞清楚getIServiceManager()方法返回的是一个什么对象呢?参考其实现: **ServiceManager.java-->ServiceManager.getIServiceManager()** ``` private static IServiceManagergetIServiceManager() { ...... // 调用asInterface,传递的参数类型为IBinder sServiceManager = ServiceManagerNative.asInterface( BinderInternal.getContextObject()); returnsServiceManager; } ``` asInterface()方法的参数为BinderInternal.getContextObject()的返回值。于是这个简短的方法中有两个内容值得讨论:BinderInternal.getContextObject()以及asInterface()。 BinderInternal.getContextObject()方法是一个native的函数,参考其实现: **android_util_Binder.cpp-->android_os_BinderInternal_getContextObject()** ``` static jobjectandroid_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) { /* 下面这句代码在卷I第6章详细分析过,它将返回一个BpProxy对象,其中 NULL(即0,用于标识目的端)指定Proxy通信的目的端是ServiceManager*/ sp<IBinder> b = ProcessState::self()->getContextObject(NULL); // 由Native对象创建一个Java对象,下面分析该函数 returnjavaObjectForIBinder(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, constsp<IBinder>& val) { //mProxyLock是一个全局的静态CMutex对象 AutoMutex _l(mProxyLock); /* val对象实际类型是BpBinder,读者可自行分析BpBinder.cpp中的findObject函数。 事实上,在Native层的BpBinder中有一个ObjectManager,它用来管理在Native BpBinder 上创建的Java BpBinder对象。下面这个findObject用来判断gBinderProxyOffsets 是否已经保存在ObjectManager中。如果是,那就需要删除这个旧的object */ jobjectobject = (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); } returnobject; } ``` 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(IBinderobj) { ......// 以obj为参数,创建一个ServiceManagerProxy对象 returnnew 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, IBinderservice) throwsRemoteException { Parceldata = Parcel.obtain(); Parcelreply = 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 jbooleanandroid_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_terr = target->transact(code, *data, reply, flags); ...... signalExceptionForError(env,obj, err); returnJNI_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 implementsIActivityManager ``` 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<JavaBBinder> get(JNIEnv* env, jobject obj) { AutoMutex _l(mLock); sp<JavaBBinder> b = mBinder.promote(); if(b == NULL) { // 创建一个JavaBBinder,obj实际上是Java层中的Binder对象 b = new JavaBBinder(env, obj); mBinder = b; } return b; } ...... private: Mutex mLock; wp<JavaBBinder> 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 voidandroid_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object) { /*parcel是一个Native的对象,writeStrongBinder的真正参数是 ibinderForJavaObject()的返回值*/ conststatus_t err = parcel->writeStrongBinder( ibinderForJavaObject(env, object)); } [android_util_Binder.cpp-->ibinderForJavaObject()] sp<IBinder> 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); } returnNULL; } ``` 根据上面的介绍会发现,addService实际添加到Parcel的并不是AMS本身,而是一个叫JavaBBinder的对象。正是将它最终传递到Binder驱动。 读者此时容易想到,Java层中所有的Binder对应的都是这个JavaBBinder。当然,不同的Binder对象对应不同的JavaBBinder对象。 图2-2展示了Java Binder、JavaBBinderHolder和JavaBBinder的关系。 :-: ![](http://img.blog.csdn.net/20150806154325282?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 图 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了。 >[info] **建议** 对此有更好的解释的读者,不妨与大家分享一下。 #### 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函数 jbooleanres = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,code, (int32_t)&data, (int32_t)reply, flags); ...... returnres != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; } ``` 就本例而言,上面代码中的mObject就是ActivityManagerService,现在调用它的execTransact()方法,该方法在Binder类中实现,具体代码如下: **Binder.java-->Binder.execTransact()** ``` private boolean execTransact(int code, intdataObj, int replyObj,int flags) { Parceldata = Parcel.obtain(dataObj); Parcelreply = Parcel.obtain(replyObj); booleanres; try { //调用onTransact函数,派生类可以重新实现这个函数,以完成业务功能 res= onTransact(code, data, reply, flags); } catch{ ... } reply.recycle(); data.recycle(); returnres; } ``` ActivityManagerNative类实现了onTransact函数,代码如下: **ActivityManagerNative.java-->ActivityManagerNative.onTransact()** ``` 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实现业务函数startActivity intresult = startActivity(app, intent, resolvedType, grantedUriPermissions, grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler); reply.writeNoException(); reply.writeInt(result); return true; } .... // 处理其他请求的case } } ``` 由此可以看出,JavaBBinder仅是一个传声筒,它本身不实现任何业务函数,其工作是: - 当它收到请求时,只是简单地调用它所绑定的Java层Binder对象的exeTransact。 - 该Binder对象的exeTransact调用其子类实现的onTransact函数。 - 子类的onTransact函数将业务又派发给其子类来完成。请读者务必注意其中的多层继承关系。 通过这种方式,来自客户端的请求就能传递到正确的Java Binder对象了。图2-3展示AMS响应请求的整个流程。 :-: ![](http://img.blog.csdn.net/20150806154338652?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 图 2 - 3 AMS响应请求的流程 在图2-3中,右上角的大方框表示AMS这个对象,其间的虚线箭头表示调用子类重载的函数。