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入门------点击打开链接
- Android------Binder java层如何与native层交互
- JNI开发中native层与Java层的交互
- Binder(native层)
- android Binder机制3---Native层
- Java层到Native层Binder的流程
- Android------Binder java层浅析
- Binder机制3---Native层
- Binder机制3---Native层
- Binder机制3---Native层
- Android Java层,Native层,Lib层打印Log简介
- Android 如何在java/native层修改一个文件的权限(mode)与用户(owner)?
- Android系统的Binder机制及其native层应用
- Android下在C++环境实现native层binder服务
- android binder机制---Java层获取ServiceManager
- Java 层Binder的使用(Android framework)
- Android java层binder解析1
- Android java层binder解析 2
- android binder - 客户端(java层) 调用 服务端(c++层) 例子
- sass的安装
- 排列组合(四)
- gitlab多人协同工作
- iOS之extern关键字
- vetor
- Android------Binder java层如何与native层交互
- python+eclipse 开发环境配置 http://pydev.org/updates
- JAVA设计模式之单例模式
- 简单判断浏览器
- STM32串口第一个字节丢失问题的分析过程
- 开篇-hello world
- HDU
- 例题 4-3 救济金发放(The Dole Queue) UVa 133
- LabVIEW上位机与串口通信