Binder 分析之Java层

本文深入解析Android系统中Binder机制的工作原理,重点介绍了Java层Binder的初始化过程,通过具体实例分析了服务注册和服务检查的流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

博客内容基于Android 8.0
因此,在分析AMS的时候和网上不一样,现在的客户端使用AMS的方法通过AIDL的方式,具体可以参考IActivityManager.aidl

Java 层的Binder 必然和Native 层的Binder有关,在分析流程的时候要时刻回忆着Native中的相关流程,这样才能更加通透的理解

一、Java层Binder的初始化

java层的Binder只是native层的一个镜像,具体的实现靠的还是native层,所以native层和java层必然有所联系,这种联系可以猜想一下靠的是JNI方式
《深入理解》书中已经指出是register_android_os_Binder函数专门负责搭建Java Binder和Native Binder交互关系

那么这个函数是什么时候被调用的呢?搜索后发现在[AndroidRuntime.cpp]中有REG_JNI(register_android_os_Binder)
REG_JNI是一个宏,先不说REG_JNI,REG_JNI(register_android_os_Binder)在数组gRegJNI中,这个数组会被函数register_jni_procs调用,看看这个方法:

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) {
\#ifndef NDEBUG
            ALOGD("----------!!! %s failed to load\n", array[i].mName);
\#endif
            return -1;
        }
    }
    return 0;
}

再向上逆推 ,register_jni_procs被AndroidRuntime::startReg调用,再向上,则是被AndroidRuntime::start调用
start方法第一句是”ALOGD(“>>>>>> START %s uid %d <<<<<<\n”,”,这个在开机log中能看到
联想到开机流程,我们发现在zyote的main函数中,初始化Java虚拟机后,会注册一些JNI函数

if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} 

再回头来看register_android_os_Binder

[android_util_Binder.cpp]
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;
    ……
}

这三个函数更详细的解释参见《深入理解》总结如下:

至此,Java Binder几个重要成员的初始化已完成,同时在代码中定义了几个全局静态对象,分别是gBinderOffsets、gBinderInternalOffsets和gBinderProxyOffsets。

框架的初始化其实就是提前获取一些JNI层的使用信息,如类成员函数的MethodID,类成员变量的fieldID等。这项工作是必需的,因为它能节省每次使用时获取这些信息的时间。当Binder调用频繁时,这些时间累积起来还是不容小觑的。

先记住这三个函数,以及这三个变量名,下面也会出现,到时候再说

二、举个栗子

1.Java层注册Service

下面通过一个AMS的实例来分析具体流程:
在ActivityManagerService.java中有setSystemProcess方法:

public void setSystemProcess() {
    try {
        //将ActivityManagerService服务注册到ServiceManager中
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
        ……
    }
     ……
}

之前分析Native Service的时候知道,有一个ServiceManager负责管理所有的service
所以 ServiceManager.addService方法必然会将服务注册到ServiceManager中,来看看具体流程:

[ServiceManager.java]
    public static void addService(String name, IBinder service, boolean allowIsolated) {
        try {
            getIServiceManager().addService(name, service, allowIsolated);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

先看看getIServiceManager返回了什么

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }
    // Find the service manage
   sServiceManager = ServiceManagerNative                                       .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
}

下面分三个知识点来详细分析

  1. getContextObject
  2. asInterface
  3. addService
1.1 getContextObject分析

BinderInternal.getContextObject()是一个native函数,具体实现在:

[android_util_Binder]
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

注意到ProcessState::self()->getContextObject,联想到之前分析defaultServiceManager()也会执行这个
因此这里的作用是,传入参数为NULL(0),获取ServiceManager进程对应的BpBinder

javaObjectForIBinder的作用是利用env和BpBinder,构造出Java对象,来细看一下:


【插入一下】下面总是出现gBinderProxyOffsets,还记得这在哪出现过吗?
是的,在最开始初始化java层Binder的时候,详细看一下:

static struct binderproxy_offsets_t
{
    // Class state.
    jclass mClass;
    jmethodID mConstructor;
    jmethodID mSendDeathNotice;

    // Object state.
    jfieldID mObject;
    jfieldID mSelf;
    jfieldID mOrgue;

} gBinderProxyOffsets;

初始化的地方在int_register_android_os_BinderProxy函数中,这个函数名这么熟悉,还记得在哪吗?是在register_android_os_Binder中
来详细看一下int_register_android_os_BinderProxy方法:

[android_util_Binder.cpps.cpp]
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, "java/lang/Error");
    gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

    clazz = FindClassOrDie(env, kBinderProxyPathName);
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderProxyOffsets.mConstructor = GetMethodIDOrDie(env, clazz, "<init>", "()V");
    gBinderProxyOffsets.mSendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
            "(Landroid/os/IBinder$DeathRecipient;)V");

    gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
    gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf",
                                                "Ljava/lang/ref/WeakReference;");
    gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");
    ……
}

通过上面的赋值,最终得到的gBinderProxyOffsets如下:

{
    jclass mClass;              //android.os.BinderProxy
    jmethodID mConstructor;     //android.os.BinderProxy.<init>() 这个init方法在哪,指的是BinderProxy的构造方法吗?
    jmethodID mSendDeathNotice;     //android.os.BinderProxy.sendDeathNotice()

    jfieldID mObject;           //android.os.BinderProxy.mObject
    jfieldID mSelf;             //android.os.BinderProxy.mSelf
    jfieldID mOrgue;            //android.os.BinderProxy.mOrgue

}

可以明显看出gBinderProxyOffsets对应的就是java层的BinderProxy类


镜头转回来继续看javaObjectForIBinder

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

    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;
    }

    // For the rest of the function we will hold this lock, to serialize
    // looking/creation/destruction of Java proxies for native Binder proxies.
    AutoMutex _l(mProxyLock);

    // Someone else's...  do we know about it?
  /*
    val对象实际类型是上面通过`ProcessState::self()->getContextObject`得到的BpBinder
    事实上,在Native层的BpBinder中有一个ObjectManager,它用来管理在Native BpBinder
    上创建的Java BpBinder对象。下面这个findObject用来判断gBinderProxyOffsets
    是否已经保存在ObjectManager中。如果是,那就需要删除这个旧的object
  */
    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) {
        jobject res = jniGetReferent(env, object);
        if (res != NULL) {
            ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
            return res;
        }
        LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }
     //创建一个新的BinderProxy对象,并注册到Native BpBinder对象的ObjectManager中
    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));
        /*
        将这个新创建的BinderProxy对象注册(attach)到BpBinder的ObjectManager中,
       同时注册一个回收函数proxy_cleanup。当BinderProxy对象撤销(detach)的时候,
        该函数会 被调用,以释放一些资源。
      */
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);

        // Also remember the death recipients registered on this proxy
        //DeathRecipientList保存了一个用于死亡通知的list
        sp<DeathRecipientList> drl = new DeathRecipientList;
        //将死亡通知list和BinderProxy对象联系起来
        drl->incStrong((void*)javaObjectForIBinder);
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

        // Note that a new object reference has been created.
        //增加该Proxy对象的引用计数
        android_atomic_inc(&gNumProxyRefs);
        //下面这个函数用于垃圾回收。创建的Proxy对象一旦超过200个,该函数
        //将调用BinderInter类的ForceGc做一次垃圾回收
        incRefsCreated(env);
    }

    return object;
}

总结:以上函数完成了以下两个工作:
· 创建了一个Java层的BinderProxy对象。
· 通过JNI,该BinderProxy对象和一个Native的BpBinder对象挂钩,而该BpBinder对象的通信目标就是ServiceManager。

1.2 asInterface分析

再来看一下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;
}

和分析native层的interface_cast一样,我们先缕一缕:


ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); 
-->getIServiceManager().addService(name, service, allowIsolated); 
-->ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject())).addService(name, service, allowIsolated) 
-->ServiceManagerNative.asInterface(BinderInternal.getContextObject()).addService(name, service, allowIsolated) -->ServiceManagerNative.asInterface(new BinderProxy()).addService(name, service, allowIsolated) 
-->new ServiceManagerProxy(new BinderProxy()).addService(name, service, allowIsolated)

所以最终调用的是ServiceManagerProxy.addService()

1.3 addService分析
[ServiceManagerNative.java]
ServiceManagerProxy::
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);
    //注意下面这个writeStrongBinder函数,service是AMS
    data.writeStrongBinder(service);
    data.writeInt(allowIsolated ? 1 : 0);
    //mRemote实际上就是BinderProxy对象,调用它的transact,将封装好的请求数据发送出去
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

跟一下transact

[BinderProxy.transact]
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    ……            
    return transactNative(code, data, reply, flags);
    ……
}

transactNative是一个native函数,定义在:

[android_util_Binder.cpp]
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    ……
    //从Java的Parcel对象中得到Native的Parcel对象
    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL) {
        return JNI_FALSE;
    }
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }
    //从Java的BinderProxy对象中得到之前已经创建好的那个Native的BpBinder对象
    //(在android_os_BinderInternal_getContextObject中创建的)
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ……
    //printf("Transact from Java code to %p sending: ", target); data->print();
    //通过Native的BpBinder对象,将请求发送给ServiceManager
    status_t err = target->transact(code, *data, reply, flags);
    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();

    ……
}

总结一下,上面跟踪的是如何添加服务到ServiceManager中

老规矩,一张图总结上面流程:
addService-form java to native

1.4 换个角度看addService

不知道大家有没有注意到,我们最初addService的时候有一个重要的参数:
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
通过整个流程下来,用到的地方在ServiceManagerProxy.addService中的data.writeStrongBinder(service)

这个this代表什么呢?writeStrongBinder又在做什么呢?下面来分析一下

这个this自然指的是ActivityManagerSerivce,看一下AMS的继承结构:

public class ActivityManagerService extends IActivityManager.Stub

这里Android O和Android N 有改动,Android N 中是

public final class ActivityManagerService extends ActivityManagerNative
public abstract class ActivityManagerNative extends Binder implements IActivityManager
public interface IActivityManager extends IInterface 

Android O 中,使用了aidl,原理应该和Android N一样,先按照Android N 分析(此处有疑问)
从编译IActivityManager.aidl生成的IActivityManager.java来看

public static abstract class Stub extends android.os.Binder implements android.app.IActivityManager

AMS会继承java层的Binder,自然会调用Binder的构造函数:

public Binder() {
    init();
    ……
}

这个init()是native方法:

[android_util_Binder.cpp]
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) {
          //创建一个JavaBBinder,obj实际上是Java层中的Binder对象
            b = new JavaBBinder(env, obj);
            mBinder = b;
            ……
        }

        return b;
    }
    ……
private:
    Mutex           mLock;
    wp<JavaBBinder> mBinder;
};

由于JavaBBinderHolder不属于Binder架构,暂时先不看,转身看看writeStrongBinder方法

[Parcel.java]
public final void writeStrongBinder(IBinder val) {
    nativeWriteStrongBinder(mNativePtr, val);   //native方法
}
[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) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}

跟踪ibinderForJavaObject

[android_util_Binder.cpp]
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;
    //如果Java的obj是Binder类,则首先获得JavaBBinderHolder对象,然后调用
    //它的get函数(没忘吧,在JavaBBinderHolder的定义中)。而这个get将返回一个JavaBBinder
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
    //如果obj是BinderProxy类,则返回Native的BpBinder对象
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }

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

而我们传入的AMS是Binder类型,所以addService实际添加到Parcel的并不是AMS本身,而是一个叫JavaBBinder的对象。正是将它最终传递到Binder驱动。

通过JavaBBinder的构造方法可以看到,JavaBBinder会把传进来的service引用赋值给自己的mObject

JavaBBinder(JNIEnv* env, jobject object)
    : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
    ……
}

综上,可以看到这三个类的关系如下图:
Binder-JavaBBinder-JavaBBinderHolder三者关系


【插入一下】【多设计一个JavaBBinderHolder的原因】

《深入理解》“为什么不直接让Java层的Binder对象指向Native层的JavaBBinder对象呢?由于缺乏设计文档,这里不便妄加揣测,但从JavaBBinderHolder的实现上来分析,估计和垃圾回收(内存管理)有关,因为JavaBBinderHolder中的mBinder对象的类型被定义成弱引用wp了”


3. AMS响应请求

看到这个Bbinder,不知道大家有没有似曾相识的感觉,在分析Native Service的时候,我们的Native Service最终继承的就是Bbinder,比如MediaPlayerService
在Native Service中,客户端使用服务的时候,是用remote()->transact()来调用服务端对应的方法
这个过程不在细说,Native Service中请求并响应简单流程如下:

remote()->transact()->BBinder.transact->BBinder.onTransact->BnMediaPlayerService.onTransact(BnMediaPlayerService继承Bbinder)

而在java层这里,在Java Serivce注册的时候,我们注册的是JavaBBinder,它是BBinder的子类。JavaBBinder并没有重写transact()函数,Transact()调用onTransact()函数。JavaBBinder重写了onTransact()的实现,这样,请求并响应流程如下:
remote()->transact()->BBinder.transact->BBinder.onTransact->JavaBBinder.onTransact

所以要看下JavaBBinder.onTransact

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

看到CallBooleanMethod就知道要回调java层 段函数,看看通过JNI回调的是哪个函数:
很容易就找到了gBinderOffsets.mExecTransact赋值的地方:
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
在int_register_android_os_Binder中(看这个函数名又是似曾相识,是在刚开始的register_android_os_Binder中调用,所以说这个函数的作用是完成重要成员的初始化)

所以,最终通过JNI调用了Binder的execTransact方法
接下来就进入java层了

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

所以会调用AMS的onTransact方法,接着向父类调用onTransact …… 不再分析了

总结:

上面缕一缕得到的结果是:
new ServiceManagerProxy(new BinderProxy()).addService(name, service, allowIsolated)

联想到Native Service,我们在addService的时候是这样说的:

defaultServiceManager()->addService
defaultServiceManager()实际返回的对象是BpServiceManager,BpServiceManager里面有mRemote变量是BpBinder类型

而ServiceManagerProxy中也有个mRemote变量,这个变量被初始化为BinderProxy类型,而mRemote又存储到BpBinder的ObjectManager中

所以,Java层的流程和Native几乎是一样的

整理结构图如下:
Java Binder整体架构图

让我们用最后一个小栗子来结束

在分析MediaPlayerService的时候,有看到过使用checkService来检查服务是否存在
Java层同样存在这个功能,看看它怎么实现的:
接口是在:

[ServiceManager]
public static IBinder checkService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return Binder.allowBlocking(getIServiceManager().checkService(name));
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in checkService", e);
        return null;
    }
}

调用了getIServiceManager().checkService(name) 前面已经分析过getIServiceManager返回的是ServiceManagerProxy类型

[ServiceManagerNative.java]
public IBinder checkService(String name) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0);
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

似曾相识吧,再看一下Native中BpServiceManager的方法:

[IServiceManager.cpp]
virtual sp<IBinder> checkService( const String16& name) const
{
    Parcel data, reply;
    data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
    data.writeString16(name);
    remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
    return reply.readStrongBinder();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值