Android------Binder java层如何与native层交互

来源:互联网 发布:matlab矩阵公式 编辑:程序博客网 时间:2024/05/22 15:40

提示:源码android7.1


在这篇文章里,我将向大家描述java层的binder是如何与native层的binder联系起来的,众所周知,java要和c++代码通讯要用到jni,其实jni技术在java里很早以前就有了,android只是把它拿过来用而已。java层的binder架构实际上也是一个C/S架构,而且其在命名上尽量保持和native层一致,它的架构其实是native层的一个镜像而已。


先把我要用到的文件列举出来:

frameworks/base/core/jni/android_util_Binder.h

frameworks/base/core/jni/android_uitl_Binder.cpp

frameworks/base/core/jni/android_os_Parcel.cpp

frameworks/base/core/java/androd/os/Binde.hava

frameworks/base/core/java/androd/os/IBinder.java

frameworks/base/core/java/com/android/internal/os/BInderInternal.java


梳理一下本文的内容:

1.讲一下重要的数据结构

2.java层binder和native层binder建立关系的过程



1》这里我有必要先说一下几个重要的数据结构:

Binder的java层框架类中有不少方法是native方法

其中java框架中的类Binder,BinderProxy,BinderInternal的native方法的实现是在android_util_Binder.cpp中

其中类Parcel中的native方法的实现是在android_os_Parcel.cpp中

static struct bindernative_offsets_t{    // Class state.    jclass mClass;    jmethodID mExecTransact;    // Object state.    jfieldID mObject;} gBinderOffsets;
gBinderOffsets结构体代表了android.os.Binder类,mClass指向class对象android.os.Binder;mExecTransact指向android.os.Binder的execTransact方法;mObject指向android.os.BInder的mObject,它将用于保存指向JavaBBinderHolder对象的指针。这里是通过int_register_android_os_Binder方法来关联的。


static struct binderinternal_offsets_t{    // Class state.    jclass mClass;    jmethodID mForceGc;} gBinderInternalOffsets;
gBinderInternalOffsets结构体代表了com.android.internal.os.BinderIntarnal类,其中mClass指向了class对象com.android.os.BinderInternal;mForceGc指向了BinderInternal的forceGC方法


static struct binderproxy_offsets_t{    // Class state.    jclass mClass;    jmethodID mConstructor;    jmethodID mSendDeathNotice;    // Object state.    jfieldID mObject;    jfieldID mSelf;    jfieldID mOrgue;} gBinderProxyOffsets;

gBinderProxyOffsets结构体代表了android.os.BinderProxy类,其中mClass指向class对象android.os.BinderProxy;mConstructor指向了BinderProxy的构造方法;mSendDeathNotice指向了BinderProxy的SendDeathNotify方法;mObject指向BinderProxy的mObject字段;mSelf指向BinderProxy的mSelf字段;mOrgue指向BinderProxy的mOrgue字段;


JavaBBinder和JavaBBinderHolder相关类类图如下所示,JavaBBinder继承自本地框架的BBinder,代表binder service服务端实体,而JavaBBinderHolder保存JavaBBinder指针,Java层Binder的mObject保存的是JavaBBinderHolder指针的值(android_os_Binder_init函数的env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);),故这里用聚合关系表示。JavaBBinder中的mObject保存的是android.os.Binder在native层的JNI对象(下面的讲解会分析到),BinderProxy的mObject保存的是BpBinder对象指针的值(这个过程下面也会分析),故此这里用聚合关系表示。


2》讲一下java层binder和native层binder建立关系的过程

要开发一个java服务,必须先继承binder类,binder类中最重要的几个成员变量如下:

 /* mObject is used by native code, do not remove or rename */    private long mObject;    private IInterface mOwner;    private String mDescriptor;
android.os.Binder类的地位和c++的BBinder类相当,它的mObject中存放的是native层关联对象的指针,实际上就是指向JavaBBinderHolder的指针。mOwner存放的是Binder继承类的引用,实际上就是Binder对象本身,mDescriptor存放的是类的描述字符串。

虽然java层的binder系统是native层的一个镜像,所以该镜像的所有工作必须要借助native层的binder系统来开展,所以要在java层正式工作之前建立这种关系,下面我要分析java层的binder框架是如何初始化的。

在AndroidRuntime.cpp中会注册很多native方法,这些方法会在系统启动的时候调用,其中就有register_android_os_Binder方法

extern int register_android_os_Binder(JNIEnv* env);

我们在android_util_BInder.cpp中找到该方法:

int register_android_os_Binder(JNIEnv* env){    if (int_register_android_os_Binder(env) < 0)        return -1;    if (int_register_android_os_BinderInternal(env) < 0)        return -1;    if (int_register_android_os_BinderProxy(env) < 0)        return -1;    jclass clazz = FindClassOrDie(env, "android/util/Log");    gLogOffsets.mClass = MakeGlobalRefOrDie(env, clazz);    gLogOffsets.mLogE = GetStaticMethodIDOrDie(env, clazz, "e",            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");    clazz = FindClassOrDie(env, "android/os/ParcelFileDescriptor");    gParcelFileDescriptorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);    gParcelFileDescriptorOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>",                                                                 "(Ljava/io/FileDescriptor;)V");    clazz = FindClassOrDie(env, "android/os/StrictMode");    gStrictModeCallbackOffsets.mClass = MakeGlobalRefOrDie(env, clazz);    gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz,            "onBinderStrictModePolicyChange", "(I)V");    return 0;}

该函数完成了java binder架构中最重要的三个类的初始化工作。其中int_register_android_os_Binder是初始化java Binder类和native层的关系,int_register_android_os_BinderInternal是初始化java BinderInternal类和native层的关系,int_register_android_os_BinderProxy是初始化java BInderProxy类和Native层的关系。

这里我们主要来看下int_register_android_os_Binder:

static int int_register_android_os_Binder(JNIEnv* env){    jclass clazz = FindClassOrDie(env, kBinderPathName);    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));}

kBinderPathName是java层binder的全名路径“android/os/Binder”,这里把gBinderOffsets的三个属性都进行了赋值,比如将gBinderOffsets的mObject赋值给了java层binder类的mObject,最后注册了gBinderMethods这个数组中的一系列方法,该数组如下:


static const JNINativeMethod gBinderMethods[] = {
     /* name, signature, funcPtr */
    { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
    { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
    { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
    { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
    { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
    { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
    { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
    { "init", "()V", (void*)android_os_Binder_init },
    { "destroy", "()V", (void*)android_os_Binder_destroy },
    { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }
};

这些方法都是JNINativeMethod,这个数组其实是一个java方法和native方法的对应表,每个数据中间的那个”()I“代表的是参数类型和返回值类型,不熟悉JNI的朋友可以去自行学习一下jni。这里我提一下android_os_Binder_init方法,它对应的是java Binder类的init方法,该方法是java binder类的初始化方法,在它的构造函数中调用:

static void android_os_Binder_init(JNIEnv* env, jobject obj){    JavaBBinderHolder* jbh = new JavaBBinderHolder();    if (jbh == NULL) {        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);        return;    }    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);    jbh->incStrong((void*)android_os_Binder_init);    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);}

该方法的工作是创建JavaBBinderHolder类的对象,并把指针保存在gBinderOffsets的mObject中(即保存在java层binder类的mObject中),因此JavaBBinderHolder类是java层binder和底层打交道的关键。

class JavaBBinderHolder : public RefBase{public:    sp<JavaBBinder> get(JNIEnv* env, jobject obj)    {        AutoMutex _l(mLock);        sp<JavaBBinder> b = mBinder.promote();        if (b == NULL) {            b = new JavaBBinder(env, obj);            mBinder = b;            ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",                 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());        }        return b;    }    sp<JavaBBinder> getExisting()    {        AutoMutex _l(mLock);        return mBinder.promote();    }private:    Mutex           mLock;    wp<JavaBBinder> mBinder;};

JavaBBinderHolder的主要作用是保存JavaBBinder的弱引用,get函数会在第一次调用时创建一个JavaBBinder对象。


JavaBBinder是从BBinder类派生,在JavaBBinder中的2个主要数据成员:

private:    JavaVM* const   mVM;    jobject const   mObject;

其中mVM保存的是java虚拟机的指针,mObject保存的是android.os.Binder在native层的JNI对象,它是在调用JavaBBinderHolder的get方法时传递进来的参数,get方法又是什么时候调用的了?是在ibinderForJavaObject方法中,ibinderForJavaObject是在android_os_Parcel_writeStrongBinder中调用,android_os_Parcel_writeStrongBinder对应了java层的nativeWriteStrongBinder方法:

{"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},

也就是writeStrongBinder方法,很熟悉的方法是不是,对了,它的源头就是我们java层的servicemanager的addService,也就是说,服务端在addService时会调用

getIServiceManager().addService(name, service, false);

getIServiceManager()的过程就不分析了,它会返回一个ServiceManagerProxy(new BinderProxy());

然后就会调用ServiceManagerProxy(new BinderProxy())的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.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);        reply.recycle();        data.recycle();    }
看到了吗,这里会调用writeStrongBinder,接着上面所说的,这里的参数IBinder service一般都是直接传入的,比如ActivityManagerService,这里的service就用的this,这样JavaBBinder中的mObject就保存了android.os.Binder在native层的JNI对象

这时,native层的BBinder对象就和java层的binder对象关联起来了,从驱动传递过来的binder调用也就有通道到达java层了。JavaBBinder重载了onTransact方法,它会调用java层binder类的execTransact方法,具体如下:

virtual status_t onTransact(        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)    {...... jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);......}

这样,IPCThreadState就通过BBinder调用到了java层,native到java层的通道也就有了。


上面分析了从native调用到java的途径,下面我就分析从java层到达native的途径:

在java层调用binder也是通过binder的代理对象来完成的,和c++类似,代理对象的生成也是通过接口类的asInterface方法来完成。在AIDL中接口类一般是自动生成的,来看下asInterface方法:

 public static com.teleepoch.aidl_application.IPerson asInterface(android.os.IBinder obj)        {            if ((obj==null)) {                return null;            }            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            if (((iin!=null)&&(iin instanceof com.teleepoch.aidl_application.IPerson))) {                return ((com.teleepoch.aidl_application.IPerson)iin);            }            return new com.teleepoch.aidl_application.IPerson.Stub.Proxy(obj);        }

这个函数逻辑和c++非常相似,先通过queryLocalInterface返回的返回值判断传入的参数是否是服务端的Binder对象,如果是就返回参数obj,否则就认为obj是引用对象,这时就返回一个新建的代理对象。这里得到这个代理对象IPerson.Stub.Proxy后,应用就会调用接口IPerson中的方法,在这些方法中会调用如下函数:

mRemote.transact(Stub.TRANSACTION_XXX,_data,_reply,0);

其中mRemote是在IPerson.Stub的构造方法中赋值的,也就是传入的obj引用对象的transact方法,那么这个obj是如何得到的了?其实java层和c++层一样,IBinder只是一个接口类,一定有一个和BpBinder作用类似的类。通常情况下我们是通过ServiceManager的getService方法来拿到这个IBinder对象(aidl中已经封装好了),来看看获取的过程:

ServiceManager的getService会调用:

return getIServiceManager().getService(name);
也就是调用的ServiceManagerProxy(new BinderProxy())的getService方法:

public IBinder getService(String name) throws RemoteException {        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IServiceManager.descriptor);        data.writeString(name);        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);        IBinder binder = reply.readStrongBinder();        reply.recycle();        data.recycle();        return binder;    }
返回的binder对象是通过Parcel类的readStrongBinder方法得到,这是一个native方法,实现是在android_os_Parcel.cpp中:

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr){    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);    if (parcel != NULL) {        return javaObjectForIBinder(env, parcel->readStrongBinder());    }    return NULL;}
仔细看该函数,javaObjectForIBinder的参数是parcel->readStrongBinder();

parcel->readStrongBinder()会返回一个c++层的IBinder对象,它实际上是一个BpBinder对象(怎样创建这里先不分析)。

而javaObjectForIBinder函数比较长,我们拿关键点说一下:

javaObjectForIBinder会创建一个java层的BinderProxy对象,该类是从Binder派生,其实在别的文章中我已经讲过java层的binder结构了,BinderProxy就是我们要找的和c++层的BpBinder对应的引用类。只不过它的对象是在native层创建的,不是在java代码中,这点比较有意思把:

jobject javaObjectForIBinder(JNIEnv* env, const sp& val){......object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);    if (object != NULL) {        LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);        // The proxy holds a reference to the native object.        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());        val->incStrong((void*)javaObjectForIBinder);        // The native object needs to hold a weak reference back to the        // proxy, so we can retrieve the same proxy if it is still active.        jobject refObject = env->NewGlobalRef(                env->GetObjectField(object, gBinderProxyOffsets.mSelf));        val->attachObject(&gBinderProxyOffsets, refObject,                jnienv_to_javavm(env), proxy_cleanup);        // Also remember the death recipients registered on this proxy        sp drl = new DeathRecipientList;        drl->incStrong((void*)javaObjectForIBinder);        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(drl.get()));        // Note that a new object reference has been created.        android_atomic_inc(&gNumProxyRefs);        incRefsCreated(env);    ......}    }

上面已经说过,这里传入的参数val是一个BpBinder对象,那么这里的env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());就把本地的BpBinder对象的引用同时放到了BinderProxy对象的mObject中(gBinderProxyOffsets.mObject对应了BinderProxy对象的mObject)。而BinderProxy的JNI对象也通过val->attachObject(&gBinderProxyOffsets, refObject,jnienv_to_javavm(env), proxy_cleanup)放到了BpBinder对象中,这样java层native层的客户端对象也关联起来了。

如果从java调用Binder服务,使用的通道就会是BinderProxy类的transact方法,对应的c++方法是android_os_BinderProxy_transact

至此,我们就了解了binder中从java到native层的途径。


总结:

上面的分析可能不是很全面,但一定会让对你binder中native到java,从java到native的交互途径都有了一个大概的理解,这里的分析其实也是把servicemanager的getservice和addservice也一起讲解了。




参考文献:《深入解析Android5.0系统》;《Android开发艺术探索》;《深入理解Android卷1》;《深入理解Android卷3》;红茶一杯话binder------点击打开链接;gityuan的binder系列------点击打开链接;罗升阳的binder系列------点击打开链接;Andriod Binder机制------点击打开链接;Android深入浅出之binder机制------点击打开链接;理解Android的binder机制-----点击打开链接;轻松理解Androidbinder------点击打开链接;binder service入门------点击打开链接