6.1.3 gBinderOffsets结构体解析

创建JavaBBinderHolder后,需要调用SetIntField将其存入gBinderOffsets.mObject中。SetIntField是JNI函数,其函数原型如下:


void SetIntField(jobject obj, jfieldID fieldID, NativeType value);


三个参数的说明如下。

Obj:非空的Java对象。

fieldID:Java对象的fieldID。

value:为fieldID设置的值。

SetIntField方法的作用是,将Native层的value存入Java层对象的某个成员变量中,其中Java层对象由obj表示,该对象的成员变量由fieldID表示。

本例中,obj即Java层的PowerManagerService对象;fieldID由gBinderOffsets.mObject指定,代表PowerManagerService的一个成员变量;value即Native层创建的JavaBBinderHolder。

通过gBinderOffsets.mObject指定了fieldID,那么这个fieldID是什么呢?

首先分析gBinderOffsets,其定义在android_util_Binder.cpp中,代码如下:


static struct bindernative_offsets_t

{

jclass mClass;

jmethodID mExecTransact;

jfieldID mObject;

}gBinderOffsets;


可见,gBinderOffsets是一个bindernative_offsets_t类型的结构体,该结构体有三个成员:mClass、mExecTransact和mObject。上文中用到了mObject成员,那么gBinderOffsets结构体是在何时初始化的呢?答案是:在Android启动阶段,通过AndroidRuntime的startReg注册JNI方法时初始化的。startReg在第4章已经分析过,该方法会执行register_android_os_Binder注册JNI方法,其位于android_util_Binder.cpp中,代码如下:


int register_android_os_Binder(JNIEnv*env)

{

//初始化Java层的android/os/Binder类与Native层的映射关系并注册JNI方法

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;

//初始化Java层的android/util/Log类与Native层的映射关系

clazz=env->FindClass("android/util/Log");

gLogOffsets.mClass=(jclass)env->NewGlobalRef(clazz);

gLogOffsets.mLogE=env->GetStaticMethodID(clazz,"e",

"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");

//建立ParcelFileDescriptor的映射关系

clazz=env->FindClass("android/os/ParcelFileDescriptor");

……//与Log的映射方式类似,省略部分代码

//建立StrictMode的映射关系

clazz=env->FindClass("android/os/StrictMode");

……//与Log的映射方式类似,省略部分代码

return 0;

}


register_android_os_Binder的主要工作是建立Java层Binder、BinderInternal、BinderProxy、Log、ParcelFileDescriptor、StrictMode与其Native层的映射关系,并对Binder、BinderInternal、BinderProxy这三个IPC通信相关的类注册其JNI方法。在int_register_android_os_Binder方法中完成了gBinderOffsets的初始化,其代码如下:


const char*const kBinderPathName="android/os/Binder";

static int int_register_android_os_Binder(JNIEnv*env)

{

jclass clazz;

//通过JNI函数得到Java层android/os/Binder类的类信息

clazz=env->FindClass(kBinderPathName);

//将android/os/Binder的类信息存入gBinderOffsets的mClass成员中

gBinderOffsets.mClass=(jclass)env->NewGlobalRef(clazz);

/*将android/os/Binder类的execTransact方法的Method ID

存入gBinderOffsets的mExecTransact成员/

gBinderOffsets.mExecTransact

=env->GetMethodID(clazz,"execTransact","(IIII)Z");

/*将android/os/Binder类的mObject成员变量的Field ID存入

gBinderOffsets的mObject成员/

gBinderOffsets.mObject

=env->GetFieldID(clazz,"mObject","I");

//注册android/os/Binder的JNI方法

return AndroidRuntime:registerNativeMethods(

env, kBinderPathName, gBinderMethods, NELEM(gBinderMethods));

}


可见,gBinderOffsets结构体是在系统启动阶段完成初始化的,其内部存储了android/os/Binder类的一些信息。

由上述代码可知,env->SetIntField(obj, gBinderOffsets.mObject,(int)jbh)将Java层的android/os/Binder类的mObject成员变量设置成JavaBBinderHolder对象的地址,而JavaBBinderHolder对象内部持有的是JavaBBinder对象的wp指针。通过gBinderOffsets, Java层的Binder类在成员变量mObject中持有Native层的JavaBBinderHolder的地址,这样Java层和Native层便建立了映射关系,通过Java层的Binder类的mObject成员变量可以获得Native层的JavaBBinderHolder对象,进而获得JavaBBinder对象。其具体的映射关系如图6-2所示。

6.1.3 gBinderOffsets结构体解析 - 图1

图 6-2 Java层和Native层的映射关系

分析到这里,获得了一个JavaBBinderHolder对象,它持有(Hold)了JavaBBinder的wp指针,而JavaBBinder是BBinder的子类,它存储了Java层系统服务的引用。因此,可以将JavaBBinder视为Java层系统服务在Native层的代表,它们都是Binder体系结构的Server端。