在阅读本文章前,如果读者还没有阅读过《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已经不陌生了。