Android7.0 Binder通信(4) Java层中的Binder

之前博客分析Binder机制时,集中分析的是Native层Binder的架构,现在来分析一下Java层Binder的架构。

一、Java层中Binder相关的主要类
Java层Binder的功能,依赖于Native层Binder来实现,可以认为Java层Binder架构是Native层Binder架构的一个镜像。
Android7.0 Binder通信(4) Java层中的Binder_第1张图片

上图为Java层Binder架构的主要成员:
1、系统定义了一个IBinder接口及DeathRecipient接口。
2、Binder类和BinderProxy类实现了IBinder接口。其中,Binder类作为Native层服务端Bn的代表,BinderProxy类作为Native层客户端Bp的代表。
3、BinderInternal类是一个仅供Binder架构使用的类;其内部有一个GcWatcher类,用于处理和Binder架构相关的垃圾回收。

二、建立Java层Binder与Native层间的关系
由于Java层的Binder需要借助Native层Binder系统来开展工作,因此初始时应该建立起Java层Binder和Native层Binder之间的联系。
这是通过JNI函数的注册完成的。

之前的博客分析zygote进程时,我们知道zyote的main函数中,初始化Java虚拟机后,会注册一些JNI函数。

//app_main.cpp的main函数
int main(int argc, char* const argv[]) 
{
    ........
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }.......
}
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
    .......
    //注册JNI函数
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    .......
}

int AndroidRuntime::startReg(JNIEnv* env)
{
    ......
    //调用JNI注册函数,其中gRegJNI数组中定义了需注册的JNI函数
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    .....
}

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        //调用对应的执行函数
        if (array[i].mProc(env) < 0) {
            ............
        }
    }
    return 0;
}

在gRegJNI数组中:

static const RegJNIRec gRegJNI[] = {
    ........
    REG_JNI(register_android_os_Binder),
    ........
}

因此,注册JNI函数时将会调用到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 BinderInternal类和Native层的关系
    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;
    //初始化Java BinderProxy类和Native层的关系
    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;
    ...........
}

上述三个JNI注册函数的风格一致:

static int int_register_android_os_Binder(JNIEnv* env)
{
    //kBinderPathName = "android/os/Binder"
    jclass clazz = FindClassOrDie(env, kBinderPathName);

    //gBinderOffsets保存Binder.java中一些信息;这样Native层就可以调用Java层中方法
    gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
    gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

    //注册JNI函数,gBinderMethods中定义了Binder.java中申明的Native方法
    return RegisterMethodsOrDie(
        env, kBinderPathName,
        gBinderMethods, NELEM(gBinderMethods));
}
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
    //kBinderInternalPathName = "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));
}
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    .................
    //kBinderProxyPathName = "android/os/BinderProxy"
    clazz = FindClassOrDie(env, kBinderProxyPathName);
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "", "()V");
    gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
            "(Landroid/os/IBinder$DeathRecipient;)V");
    .................
    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}

从上面的代码,我们可以看出Binder初始时注册JNI函数的目的主要有两个:
1、Java层申明了Native函数,因此在初始时为其注册对应的JNI实现函数;
2、Native层获取Java层对应的一些方法和成员,为后续的调用埋下伏笔。

Binder建立起Java层和Native层的联系后,我们通过一个例子看看,Java层的对象如何使用Binder类。

三、实例分析

1、Java层服务注册
之前的博客以Native层服务为例,分析了服务如何注册到ServiceManager进程,现在以Java层的服务ActivityManagerService为例,看看Java层的服务是如何完成注册的。
SystemServer创建出ActivityManagerService后,最终将调用其setSystemProcess方法:

public void setSystemProcess() {
    try {
        //注册服务,第二个参数为this
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
        ..........
    } catch (PackageManager.NameNotFoundException e) {
        ........
    }
}

跟进ServiceManager.java中的addService函数:

//第二个参数类型为IBinder
public static void addService(String name, IBinder service, boolean allowIsolated) {
    try {
        //我们知道服务实际上应该注册到ServiceManager进程,那么getIServiceManager如何获取到ServiceManager进程的代理对象?
        getIServiceManager().addService(name, service, allowIsolated);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }

    // Find the service manager
    //是否感觉这里和Native层利用IInterface体系,转换BpBinder为BpXXX(XXX为实际服务)很像?
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

1.1 BinderInternal.getContextObject
我们先看看BinderInternal类中的getContextObject方法:

public static final native IBinder getContextObject();

我们看看其对应的实现函数(定义于android_util_Binder.cpp中):

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    //之前的博客已经分析过,ProcessState::self将创建出ProcessState实例,执行打开Binder设备等操作
    //此处调用ProcessState的getContextObject方法,传入参数为NULL(0),将获取ServiceManager进程对应的BpBinder
    sp b = ProcessState::self()->getContextObject(NULL);
    //利用环境变量和BpBinder构造出java object
    return javaObjectForIBinder(env, b);
}

我们看看javaObjectForIBinder函数:

jobject javaObjectForIBinder(JNIEnv* env, const sp& val) {
    if (val == NULL) return NULL;

    //如果val是Binder对象,进入下面分支,此时val是BpBinder
    if (val->checkSubclass(&gBinderOffsets)) {
        // One of our own!
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }
    .........
    //调用BpBinder的findObject函数
    //在Native层的BpBinder中有一个ObjectManager,它用来管理在Native BpBinder上创建的Java BinderProxy对象
    //findObject用于判断gBinderProxyOffsets中,是否存储了已经被ObjectManager管理的Java BinderProxy对象
    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) {
        jobject res = jniGetReferent(env, object);
        ............
        //如果该Java BinderProxy已经被管理,则删除这个旧的BinderProxy
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }

    //创建一个新的BinderProxy对象
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        // 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));

        //新创建的BinderProxy对象注册到BpBinder的ObjectManager中,同时注册一个回收函数proxy_cleanup
        //当BinderProxy对象detach时,proxy_cleanup函数将被调用,以释放一些资源
        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);
        //将死亡通知list和BinderProxy联系起来
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(drl.get()));

        // Note that a new object reference has been created.
        android_atomic_inc(&gNumProxyRefs);

        //垃圾回收相关;利用gNumRefsCreated记录创建出的BinderProxy数量
        //当创建出的BinderProxy数量大于200时,该函数将利用BinderInternal的ForceGc函数进行一个垃圾回收
        incRefsCreated(env);

        return object;
    }
}

从代码来看,BinderInternal.getContextObject的函数细节比较丰富,但实质上的目的就是:得到ServiceManager进程对应的BpBinder,然后利用该BpBinder构造出Java层的BinderProxy对象。

1.2 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);
}
public ServiceManagerProxy(IBinder remote) {
    //保存BinderProxy对象
    mRemote = remote;
}

可以看到ServiceManagerNative的asInterface函数,实际上类似于Native层的interface_cast宏,都是以一个BpProxy对象为参数构造一个和业务相关的Proxy对象。
此处,利用BinderProxy对象构造出ServiceManagerProxy对象。ServiceManagerProxy的各个业务函数会将相应的请求打包后递交给BinderProxy对象,BinderProxy对象将利用BpBinder将消息发送给Binder驱动。

1.3 ServiceManagerProxy.addService
ServiceManagerProxy为定义在ServiceManagerNative.java中的内部类,我们看看它的addService函数:

public void addService(String name, IBinder service, boolean allowIsolated) 
        throws RemoteException {
    //将数据打包写入Parcel对象
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    //注意这个地方,后文分析,此时的service为ActivityManagerService
    data.writeStrongBinder(service);
    data.writeInt(allowIsolated ? 1 : 0);
    //调用BindProxy的transact函数
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

接下来看看BinderProxy的transact函数:

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
    if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
    //实际上通过Native函数发送
    return transactNative(code, data, reply, flags);
}

看看对应的Native函数:

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags)
{
    ........
    //将java对象转化为native对象
    Parcel* data = parcelForJavaObject(env, dataObj);
    .........
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ........
    //得到native层的BpBinder
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ........
    //通过BpBinder利用IPCThreadState,将请求通过Binder驱动发送给ServiceManager进程
    status_t err = target->transact(code, *data, reply, flags);
    ........
}

通过上面的代码,我们可以看出Java层的Binder架构,最终要是依赖于Native层的Binder架构进行实际的通信过程,整个架构如下图所示:
Android7.0 Binder通信(4) Java层中的Binder_第2张图片

2 Java层服务端绑定Native Binder
上面分析服务注册流程时,我们知道了如何获取ServiceManager进程的Java层Binder代理对象。通过这个流程,我们实际上知道了Java层的客户端是如何绑定到Native Binder架构的。

现在我们看看Java层的服务端使如何绑定到Native Binder架构的。
我们同样可以用ActivityManagerService为例,ActivityManagerService自身就是一个基于Binder通信的服务端。

我们先要看看ActivityManagerService的继承结构。

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ...........
}

public abstract class ActivityManagerNative extends Binder implements IActivityManager {
    ...........
}

从上面的代码我们可以看出,ActivityManagerService继承自ActivityManagerNative,后者继承自Java层的Binder。
因此当ActivityManagerService被创建后,最终将调用到Binder的构造函数:

public Binder() {
    //native层的init函数
    init();

    if (FIND_POTENTIAL_LEAKS) {
        ..........
    }
}

我们跟进init函数:

static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    //创建一个JavaBBinderHolder对象
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    ...........
    jbh->incStrong((void*)android_os_Binder_init);
    //将JavaBBinderHolder对象保存到Java层的Binder对象的mObject成员中
    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}

从上面的代码可以看出,Java的Binder对象将和一个Native层的JavaBBinderHolder对象相关联。
跟进JavaBBinderHolder类:

class JavaBBinderHolder : public RefBase
{
public:
    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
    {
        AutoMutex _l(mLock);
        sp<JavaBBinder> b = mBinder.promote();
        if (b == NULL) {
            //JavaBBinderHolder中持有了JavaBBinder, obj实际上是Java层中的Binder对象
            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;
    }
    .............
}

从代码来看,JavaBBinderHolder仅从RefBase派生,实际上不属于Binder架构。但它的get函数将创建出JavaBBinder对象,该对象继承自Native层的BBinder对象。

那么JavaBBinderHolder的get函数什么时候会被调用呢?

实际上,在上文ServiceManagerProxy的addService函数中:

//调用了JavaParcel的writeStrongBinder函数
data.writeStrongBinder(service);
public final void writeStrongBinder(IBinder val) {
    //调用了native函数
    nativeWriteStrongBinder(mNativePtr, val);
}

我们看看android_os_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) {
        //native层的parcel
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;

    //obj为Binder类
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        //调用了JavaBBinderHolder的get方法
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }

    //obj为BinderProxy类
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }

    ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
    return NULL;
}

通过上面的代码,我们可以看到当一个服务进行注册时,会将Java层的Binder对象和Native层的BBinder关联起来,于是服务端绑定到了Native层的Binder架构。
此外,addService中打包传入的其实不是ActivityManagerService本身,而是对应的JavaBBinder对象。
这里对应的结构如下图所示:
Android7.0 Binder通信(4) Java层中的Binder_第3张图片

3、ActivityManagerService响应请求
之前博客分析Native层的Binder架构时,我们知道服务端进程对应的BBinder收到数据后,将调用子类的onTransact进行处理。
对于Java层的服务,从上面的继承体系,我们知道首先应该由JavaBBinder的onTransact进行处理:

virtual status_t onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
    //从Java虚拟机中得到调用JNI函数所需的结构体
    JNIEnv* env = javavm_to_jnienv(mVM);
    .......
    //通过JNI调用Java层的execTransact函数
    jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, reinterpret_cast(&data), reinterpret_cast(reply), flags);
    .......
}

从继承体系来看,我们应该跟进Java层的Binder:

private boolean execTransact(int code, long dataObj, long replyObj,
        int flags) {
    .........
    try {
        //调用子类的onTransact函数
        res = onTransact(code, data, reply, flags);
    }.......... 
}

对于ActivityManagerService来说,直接继承Binder的子类为ActivityManagerNative:

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    switch (code) {
    //根据code执行实际的业务
    case START_ACTIVITY_TRANSACTION:
    {
        .........
    }

    case START_ACTIVITY_AS_USER_TRANSACTION:
    {
        .......
    }
    ............
}

从上面的代码可以看出,Native层的BBinder收到数据后,通过JNI函数递交到Java层的Binder对象。Java层的Binder对象将调用实际业务的函数进行处理。

4、整体总结
Android7.0 Binder通信(4) Java层中的Binder_第4张图片
如上图所示,Java层的Binder通信其实就是通过JNI函数,嫁接到Native层的Binder架构之上。
在理解了Native层Binder架构之后,整个通信框架还是比较好理解的。

你可能感兴趣的:(Android源码学习笔记)