Android Binder Java

在阅读本文章前,如果读者还没有阅读过《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.0 Client Client JavaBBinder JavaBBinder Binder Binder 子类 子类 收到调用 调用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已经不陌生了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值