Android Binder Java
来源:互联网 发布:relief算法应用 编辑:程序博客网 时间:2024/06/05 09:01
在阅读本文章前,如果读者还没有阅读过《android Binder Native》,强烈建议先去阅读这篇文章,否则你可能有的地方会不明白。
如果你已经读过了上篇文章,那么对于BpBinder、BBinder应该有了一定了解,在Java层的Binder也是一个C/S架构,而且在命名上尽可能的保持与Native层一致,所以大家可以认为,Java Binder 是Native Binder的一个镜像版本。下面先来看下Java Binder 中的相关类。
- Binder代表了Bn端(相当于服务端)
- BinderProxy 代表了Bp端(相当于客户端)
- BinderInternal只是一个仅供Binder使用的类,内部定义了一个GCWatcher用来处理Binder相关的回收
了解了Java Binder 的大致关系后,我们要想一下,Java层代码 是如何与Native层关联的? 有的人会问,为啥要关联?? MMP, Android是Linux系统,肯定是要借助Native层的 C 代码来操作底层硬件了…. 下面分析Java Binder和Native Binder是如何建立起联系的
以下Native代码使用在线阅读网站:http://androidxref.com/进行阅读,且代码版本为 7.1.1_r6 , Java代码版本 API23
Java Binder的初始化
在Android系统中,在Java创建初期的时,系统会提前注册一些JNI(Java 和 Native 通信的桥梁,不懂的同学自行查阅~)函数,其中就有一个函数是用来专门负责搭建 Java Binder 和Native Binder关系的。它在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 binder internal 和native 层关系 if (int_register_android_os_BinderInternal(env) < ) return -1; //初始化 java binderproxy 和native层关系 if (int_register_android_os_BinderProxy(env) < 0) return -1; .... return 0;}
上面代码完成了3个操作
- 关联 Java Binder 和Native
- 关联 Java BinderInternal 和Native
- 关联 Java BinderProxy 和Native
下面一一分析。
static int int_register_android_os_Binder(JNIEnv* env){ //kBinderPathName 为 "android/os/Binder" jclass clazz = FindClassOrDie(env, kBinderPathName); //静态类对象,专门保存Binder类在JNI层的一些信息 gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z"); gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J"); //注册 return RegisterMethodsOrDie( env, kBinderPathName, gBinderMethods, NELEM(gBinderMethods));}
看上面代码我们需要知道
- gBinderOffset 是一个静态类对象,它专门保存Binder在JNI层的一些使用信息
- 获取信息 并赋值给 gBinderOffsets.mExecTransact 和 mObject 这些都是JNI 对Java层 Binder进行操作时 所需要的
static int int_register_android_os_BinderInternal(JNIEnv* env){ // PathName com/android/internal/os/BinderInternal jclass clazz = FindClassOrDie(env, kBinderInternalPathName); gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V"); return RegisterMethodsOrDie( env, kBinderInternalPathName, gBinderInternalMethods, NELEM(gBinderInternalMethods));}
看代码可以知道跟 Binder 的代码基本类似。
static int int_register_android_os_BinderProxy(JNIEnv* env){ // Error类 jclass clazz = FindClassOrDie(env, "java/lang/Error"); gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz); // Proxy clazz = FindClassOrDie(env, kBinderProxyPathName); gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V"); //应该是用于 Binder 内的 DeathRecipient通知. gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice","(Landroid/os/IBinder$DeathRecipient;)V"); gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J"); // 弱引用 赋值mSelf gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf","Ljava/lang/ref/WeakReference;"); gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J"); clazz = FindClassOrDie(env, "java/lang/Class"); gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;"); return RegisterMethodsOrDie( env, kBinderProxyPathName, gBinderProxyMethods, NELEM(gBinderProxyMethods));}
相比与Binder 与BinderInternal,BinderProxy的初始化关联代码可能稍微复杂一点,它主要做了如下操作
- 找到Error类
- 找到根据pathName找到BinderProxy 赋值给gBinderProxyOffsets.mClass
- 使用弱引用 并赋值给 mSelf
由上面这些代码可以看出来,3部主要定义了几个全局的静态变量,分别是gBinderOffsets、gBinderInternalOffsets、gBinderProxyOffsets,并获取了一些JNI使用Java Binder的一些函数,如: MethID、fieldID等,最后通过RegisterMethodsOrDie 来真正的搭建 Native 与Java的通信。
初始化完成了,我们接下来分析 它的工作流程(通过ActivityManagerService,简称AMS)。
如果大家看了上一篇文章《android Binder Native》的话,那么就应该知道,Binder消息最终会由ServiceManager来管理,如果要接受 那么就需要将自己注册到ServiceManager内,所以接下来我们要研究的内容如下
- AMS如何将自己注册进ServiceManager
- AMS如何响应客户端的Binder调用请求
我们从AMS的setSystemProcess为起点来看
public void setSystemProcess() { try { ServiceManager.addService(Context.ACTIVITY_SERVICE,this,true); ..... }
很清晰,没毛病。第一行代码就直接把自己加入到了ServiceManager中
public static void addService(String name, IBinder service) { try { getIServiceManager().addService(name, service, false); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } }
可以看到,这里调用了getIServiceManager()的addService, 它又是个啥东东?
private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }
竟然调用了ServiceManagerNative.asInterface() 和 BinderInternal.getContectObject(),如果大家阅读过前一篇,那么就应该会很熟悉了。我们来看getContextObject()
public static final native IBinder getContextObject();
在BinderInternal内,它是一个native方法,我们直接转到在Binder.cpp 的android_os_BinderInternal_getContextObject()内
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz){ sp<IBinder> b = ProcessState::self()->getContextObject(NULL); //创建一个Java Binder对象 return javaObjectForIBinder(env, b);}
上面代码首先是调用了 ProcessState的getContextObject(NULL)方法,该方法返回的实际是一个BpBinder,如果有不熟悉的同学,由于篇幅较多,这里就不在叙述,请大家转移至上一篇文章/
接下来我们看 javaOBjectForIBinder(),该函数在Native创建了一个Java Binder对象。
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val){ ..... AutoMutex _l(mProxyLock); jobject object = (jobject)val->findObject(&gBinderProxyOffsets); if (object != NULL) { .... android_atomic_dec(&gNumProxyRefs); val->detachObject(&gBinderProxyOffsets); env->DeleteGlobalRef(object); } object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); if (object != NULL) { env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get()); val->incStrong((void*)javaObjectForIBinder); jobject refObject = env->NewGlobalRef( env->GetObjectField(object, gBinderProxyOffsets.mSelf)); //将新建的BinderProxy注册到BpBinder的ObjecrtManager中 //并注册回调函 proxy_cleanup,以便在BinderProcy(detach)时回收资源 val->attachObject(&gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup); //用户死亡通知的list sp<DeathRecipientList> drl = new DeathRecipientList; drl->incStrong((void*)javaObjectForIBinder); //将死亡通知的list 和BinderProxy联系起来 env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get())); //增加proxy对象引用计数 android_atomic_inc(&gNumProxyRefs); //用于垃圾回收。创建的Proxy对象超过200个,则调用BinderInternal内的GCWatcher进行响应回收。 incRefsCreated(env); } return object;}
看代码我们知道 首先调用了 val->findObject(), 然而val就是BpBinder, BpBinder的findObject 主要功能是 查找gBinderProxyOffsets 是否存在ObjectManager中,如果存在就返回。 这里又突然蹦出来个ObjectManager,这是啥东西?? 它实际存在于 BpBinder中,负责管理在Native层中创建的 Java BinderProxy对象。
接下来又创建了一个新的BinderProxy,然后调用attachObject.于BpBinder关联,BpBinder的目的段又是ServiceManager。所以该准备的也都准备就绪了。 以上代码主要做了如下事件:
- 创建一个Java层的BinderProxy
- 通过attachObject 将Java层 BinderProxy与 BpBinder进行关联
- 返回BinderProxy
接下来看ServiceManagerNative.asInterface
static public IServiceManager asInterface(IBinder obj) { if (obj == null) { return null; } IServiceManager in =(IServiceManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ServiceManagerProxy(obj); }
可以看到,最终以BpProxy对象为 参数,构造了一个ServiceManagerProxy(BpProxy), 这种结构和Interface.h 里面定义的宏是一个套路,以BpProxy为参数构造一个和业务相关的Proxy对象。我们来看ServiceManagerProxy 的addService
public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); //该函数需要注意 data.writeStrongBinder(service); data.writeInt(allowIsolated ? 1 : 0); //mRemote实际上是BinderProxy对象,调用它的transact将封装好的请求发送出去。 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); reply.recycle(); data.recycle(); }
我们先来看data.writeStrongBinder 它是一个特别的函数,为了让大家能够知道具体是怎么特别,我们先来看以下知识点。
AMS从ActivityManagerNative派生,并且ActivityManagerNative 从Binder派生,我们直接看Binder的构造期就好了。
public Binder() { init(); .... }
调用了init方法,该方法是native的
static void android_os_Binder_init(JNIEnv* env, jobject obj){ //创建一个JavaBBinderHolder JavaBBinderHolder* jbh = new JavaBBinderHolder(); if (jbh == NULL) { jniThrowException(env,"java/lang/OutOfMemoryError", NULL); return; } jbh->incStrong((void*)android_os_Binder_init); //将这个JavaBBinderHolder 保存到 Java Binder对象的mObject中 env->SetLongField(obj, gBinderOffsets.mObject,(jlong)jbh);}
上面创建了一个Native的 JavaBBinderHolder对象,并且将它与Java Binder对象进行了关联。
class JavaBBinderHolder : public RefBase{public: sp<JavaBBinder> get(JNIEnv* env, jobject obj) { .... sp<JavaBBinder> b = mBinder.promote(); if (b == NULL) { b = new JavaBBinder(env, obj); mBinder = b; .... } return b; }
可以看到JavaBBinderHolder派生RefBase,并不在 Binder的家族链,但是get函数里面新建了一个 JavaBBinder(env,Java中的Binder对象),而JavaBBinder从BBinder派生。那么问题来了,get函数是哪里调用的??? 不要着急,我来告诉你,它就在data.writeStrongBinder中…
Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object){ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL){ //实际是一ibinderForJavaObject 的返回作为参数 const status_t err = parcel- >writeStrongBinder(ibinderForJavaObject(env, object)); if (err != NO_ERROR) { signalExceptionForError(env, clazz, err); } }}
可以看到这里实际以ibinderForJavaObject返回做参数
Binder.cpp ibinderForJavaObject()
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj){ if (obj == NULL) return NULL; if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject); return jbh != NULL ? jbh->get(env, obj) : NULL; } if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { return (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); } return NULL;}
从上面代码可以看到,如果obj属于Binder那么把 gBinderOffsets.mObject对象取出来,该对象实际就是JavaBBinderHolder,然后调用该对象的get函数 ,其内部会创建一个JavaBBinder对象,并赋值给JavaBBinderHolder的mBinder。 如果属于BinderProxy,那么则取出gBinderProxyOffsets.mObject对象,实际是BpBinder,然后返回。
所以由上面代码可知,ServiceManager.addService实际加入的不是ActivityManagerService,而是一个JavaBBinder对象。我们需要知道
- Java的Binder通过mObject指向Native层的JavaBBinderHolder对象
- JavaBBinderHolder 的mBinder 指向一个Native的 JavaBBinder
- Native 的JavaBBinder又通过mObject变量指向一个Java层的Binder对象。
data.writeStrongBinder解析完了,那么接下来看 transact
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,jint code, jobject dataObj, jobject replyObj, jint flags){ .... Parcel* data = parcelForJavaObject(env, dataObj); if (data == NULL) { return JNI_FALSE; } Parcel* reply = parcelForJavaObject(env, replyObj); if (reply == NULL && replyObj != NULL) { return JNI_FALSE; } .... IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); .... status_t err = target->transact(code, *data, reply, flags); signalExceptionForError(env, obj, err, true,data->dataSize()); return JNI_FALSE; }
上面代码主要做了如下几件事
- Parcel data = parcelForJavaObject 从Java的 Parcel对象中得到 Native的Parcel对象
- Parcel* reply = parcelForJavaObject 用于得到一个用于回复的Parcel对象
- 从BpProxy中获取之前创建好的BpBinder
- 调用BpBinder的transact,最后会发送给ServiceManager
关于ActivityManagerService如何将自己注册到ServiceManager的已经分析完,下面我们接着分析ActivityManagerService是如何响应请求的。
从Native的 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(); const int32_t strict_policy_before = thread_state->getStrictModePolicy(); //这里调用Java Binder层的 execTransact函数 //mObject就是 AMS jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); .... return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;;}
从上面代码可以看到,调用了 ActivityManagerSerivce 的exectransact方法(gBinderOffsets.mExecTransact),为什么会调用? 请迅速的向上翻,并找到Java Binder 和Native关联时所调用的GetMethodIDOrDie方法。
exectransact在Binder类中定义,我们来看代码。
private boolean execTransact(int code, long dataObj, long replyObj,int flags) { Parcel data = Parcel.obtain(dataObj); Parcel reply = Parcel.obtain(replyObj); try { res = onTransact(code, data, reply, flags); } .... .... .... return res; }
这里Binder的子类 可以覆盖onTransact方法,来完成业务功能需求。按ActivityManagerService来说的话,它重新实现来onTransact,它会先进行一些处理,然后调用super.onTransact 也就是ActivityManagerNative的onTransact,在其内 会进行各种case 来处理相应的情况。
现在 有关AMS如何注册到ServiceManager内 和AMS如何响应已经解析完了,根据分析我们大体得知
- 对于客户端的BinderProxy来说,Java层的BinderProxy 对应一个 Native层的BpBinder。从Java层发送的请求 都是从BinderProxy到 BpBinder 然后由BpBinder发送请求到Binder驱动
- 对于服务端的Service来说,Java层的Binder对应一个Native层的JavaBBinder。JavaBBinder起到中转作用,把客户端的请求从Native层传到Java层。
相信到这里,大家对于Binder已经不陌生了。
- Android Binder Java
- Android JAVA Binder IPC System
- Android Java Binder 通信机制
- Android------Binder java层浅析
- Android 6.0 理解Java Binder
- Android Binder -什么是binder
- android local service, service.java , binder
- android binder机制---Java层获取ServiceManager
- Java 层Binder的使用(Android framework)
- Android java层binder解析1
- Android java层binder解析 2
- Android Binder
- Android Binder
- android Binder
- Android-binder
- android Binder
- Android--Binder
- android binder
- 2017-Java面试必看问题之一
- 【Java8源码分析】NIO包-FileChannel
- 关于Error: ARCH: Unsupported platform.
- JSOUP学习笔记
- 广播接收者之有序广播
- Android Binder Java
- Java分布式应用技术架构介绍
- 如何利用jqGrid表格方法重新设置caption属性值
- 在不使用额外空间的前提下,将数组的偶数放到数组的奇数前面 | Python
- Codeforces Round #418 (Div. 2) 题解 ABC
- 使用CSS确定HTML中的断句格式——你真的了解word-wrap和word-break的区别吗
- 后台启动zookeeper
- 关于Retrofit使用HTTPS的相关问题
- 淘宝开源Key/Value结构数据存储系统Tair技术剖析