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 中的相关类。

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 来处理相应的情况。

Created with Raphaël 2.1.0ClientClientJavaBBinderJavaBBinderBinderBinder子类子类收到调用调用Binder对象的execTransact调用子类onTransact函数

现在 有关AMS如何注册到ServiceManager内 和AMS如何响应已经解析完了,根据分析我们大体得知

  • 对于客户端的BinderProxy来说,Java层的BinderProxy 对应一个 Native层的BpBinder。从Java层发送的请求 都是从BinderProxy到 BpBinder 然后由BpBinder发送请求到Binder驱动
  • 对于服务端的Service来说,Java层的Binder对应一个Native层的JavaBBinder。JavaBBinder起到中转作用,把客户端的请求从Native层传到Java层。

相信到这里,大家对于Binder已经不陌生了。

原创粉丝点击