IPC机制(六)——Binder原理分析(二)

Binder整体架构

image

之前的文章从binder驱动层,到最终要的ServiceManager,分析了ServiceManager的启动,开启一个服务进行binder通信如何获取到ServiceManager,以及注册服务和获取服务。整个流程下来,对binder通信的理解是更深了一层。不只是觉得它浮于表面了。

上面的binder整体架构图出自一位大神之手。从图中可以看到binder在framework层,采用JNI技术来调用native(c/c++)层的binder架构,从而为上层应用程序提供服务。native层也是分为C/S架构,分为Bn(server)端和Bp(client)端,同样实现了一套IPC通信架构。

图解:

  • 图中红色代表整个framework层binder架构相关组件
    • Binder类代表Server端,BinderProxy类代表Client端
  • 图中蓝色代表Native层Binder架构相关组件
  • 上层framework层的Binder逻辑是建立在Native层架构基础之上的,核心逻辑都是交予Native层方法来处理的。
  • framework层的ServiceManager类与Native层的功能并不完全对应,framework层的ServiceManager类的实现最终是通过BinderProxy传递给Native层来完成的。

Binder类图

image

这张图出自gityuan之手,他把framework层和Binder相关的类之间的关系都表示很清楚,主要就是Binder和ServiceManager,主要就是要去搞清楚上层和底层的Binder是如何交互的。先看看这几个类分别在干什么。

  1. ServiceManager:通过getIServiceManager方法获取的是ServiceManagerProxy对象;ServiceManager的addService,getService实际工作都由ServiceManagerProxy的相应方法来处理;
  2. ServiceManagerProxy: 其成员变量mRemote指向BinderProxy对象,ServiceManagerProxy的addService,getService方法最终是交由mRomate来完成;
  3. ServiceManagerNative:其方法asInterface()返回的是ServiceManagerProxy对象,ServiceManager便是借助ServiceManagerNative类来找到ServiceManagerProxy;
  4. Binder:其成员变量mObject和方法execTransact()用于native方法
  5. BinderInternal:内部有一个GcWatcher类,用于处理和调试与Binder相关的垃圾回收
  6. IBinder:接口常量FLAG_ONEWAY:客户端利用Binder跟服务端通信是阻塞式的,但如果设置了FLAG_ONEWAY,这成为非阻塞式的调用方式,客户端能立即返回,服务端采用回调方式来通知客户端完成情况。另外IBinder接口有一个内部接口DeathDecipient(死亡通告)

根据这几个类的作用在去源码中看看,整个Binder从Kernel至Native,JNI,Framework层到底是怎么串到一起的。

初始化

在Android系统开机过程中,Zygote启动时会有一个虚拟机注册过程,该过程调用AndroidRunntime::startReg方法来完成jni方法的注册

startReg

int AndroidRuntime::startReg(JNIEnv* env)
{
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    env->PushLocalFrame(200);

    //注册jni方法
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);

    return 0;
}

注册jni方法,其中gRegJNI是一个数组,记录所有需要注册的jni方法,其中有一项就是REG_JNI(register_android_os_Binder)。

register_android_os_Binder

int register_android_os_Binder(JNIEnv* env) {
    // 注册Binder类的jni方法
    if (int_register_android_os_Binder(env) < 0)
        return -1;

    // 注册BinderInternal类的jni方法
    if (int_register_android_os_BinderInternal(env) < 0)
        return -1;

    // 注册BinderProxy类的jni方法
    if (int_register_android_os_BinderProxy(env) < 0)
        return -1;
    ...
    return 0;
}

注册Binder

static int int_register_android_os_Binder(JNIEnv* env) {
    //其中kBinderPathName = "android/os/Binder";查找kBinderPathName路径所属类
    jclass clazz = FindClassOrDie(env, kBinderPathName);

    //将Java层Binder类保存到mClass变量;
    gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    //将Java层execTransact()方法保存到mExecTransact变量;
    gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
    //将Java层mObject属性保存到mObject变量
    gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");

    //注册JNI方法
    return RegisterMethodsOrDie(env, kBinderPathName, gBinderMethods,
        NELEM(gBinderMethods));
}

注册Binder的方法中一直在和java层的Binder打交道。把有关Binder的重要变量都保存到了gBinderOffsets中。主要有三步:

  1. mClass:保存java层的Binder类
  2. mExecTransact:保存execTransact()方法
  3. mObject:保存mObject属性

gBinderOffsets

gBinderOffsets是全局静态结构体,定义如下:

static struct bindernative_offsets_t
{
    jclass mClass; //记录Binder类
    jmethodID mExecTransact; //记录execTransact()方法
    jfieldID mObject; //记录mObject属性

} gBinderOffsets;

gBinderOffsets保存了Binder.java类本身以及成员方法execTransact()和成员属性mObject,这为JNI层访问java层提供通道。另外是通过查询获取java层Binder信息后保存到gBidnerOffsets不需要每次查找binder类信息的方式大幅度提高效率。解决了每次查询需要花费较多cpu事件,用结构体保存也是一种空间换时间的方法。

去看看Binder.java中的这三个重要的竖向和方法:

//指向JavaBBinderHolder对象的原始本机指针。由此java对象拥有,不为空。
private final long mObject;

//mObject出现在Binder中
public Binder() {
    mObject = getNativeBBinderHolder();//调用native层的方法
    ····
}

可以看出在execTransact方法中调用了onTransact方法向Binder线程池发送Parcel数据
//android_util_Binder.cpp的onTransact的入口
private boolean execTransact(int code, long dataObj, long replyObj,
            int flags) {
        BinderCallsStats binderCallsStats = BinderCallsStats.getInstance();
        BinderCallsStats.CallSession callSession = binderCallsStats.callStarted(this, code);
        Parcel data = Parcel.obtain(dataObj);
        Parcel reply = Parcel.obtain(replyObj);
      
        boolean res;
       
        final boolean tracingEnabled = Binder.isTracingEnabled();
        try {
            if (tracingEnabled) {
                Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
            }
            res = onTransact(code, data, reply, flags);
        } catch (RemoteException|RuntimeException e) {
            if (LOG_RUNTIME_EXCEPTION) {
                Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
            }
            if ((flags & FLAG_ONEWAY) != 0) {
                if (e instanceof RemoteException) {
                    Log.w(TAG, "Binder call failed.", e);
                } else {
                    Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
                }
            } else {
                reply.setDataPosition(0);
                reply.writeException(e);
            }
            res = true;
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
        reply.recycle();
        data.recycle();

        StrictMode.clearGatheredViolations();
        binderCallsStats.callEnded(callSession);

        return res;
    }

//Binder实现了IBinder,Binder是远程对象的基类,我们一般在aidl文件中继承Binder实现了自定义的RPC协议。Binder类只是一个基本的IPC原语,它对应用程序的生命周期并且在创建它的进程中运行才有效。
public class Binder implements IBinder     

gBinderMethods

static const JNINativeMethod gBinderMethods[] = {
     /* 名称, 签名, 函数指针 */
    { "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 }
};

RegisterMethodsOrDie()中为gBinderMethods数组中的方法建立了一一映射关系,从而为java层访问JNI层提供通道。

int_register_android_os_Binder方法的主要功能:

  • 通过gBinderOffsets,保存java层Binder类的信息,为JNI层访问java层提供通道
  • 通过RegisterMethodsOrDie,将gBinderMethods数组完成映射关系,从而为java层访问jni层提供通道。

也就是说该过程建立了Binder类在Native层与framework层之间相互调用的桥梁。

注册BinderInternal

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

注册了BinderInternal类的jni方法,gBinderInternalOffsets保存了BinderInternal的forceBinderGC()方法。

下面是BinderInternal类的jni方法注册:

static const JNINativeMethod gBinderInternalMethods[] = {
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
    { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
    { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
};

和注册Binder非常类似,该过程建立了BinderInternal类在Native层与framework层之间的相互调用的桥梁。

注册BinderProxy

static int int_register_android_os_BinderProxy(JNIEnv* env) {
    //gErrorOffsets保存了Error类信息
    jclass clazz = FindClassOrDie(env, "java/lang/Error");
    gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);

    //gBinderProxyOffsets保存了BinderProxy类的信息
    //其中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");
    gBinderProxyOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
    gBinderProxyOffsets.mSelf = GetFieldIDOrDie(env, clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
    gBinderProxyOffsets.mOrgue = GetFieldIDOrDie(env, clazz, "mOrgue", "J");

    //gClassOffsets保存了Class.getName()方法
    clazz = FindClassOrDie(env, "java/lang/Class");
    gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");

    return RegisterMethodsOrDie(
        env, kBinderProxyPathName,
        gBinderProxyMethods, NELEM(gBinderProxyMethods));
}

注册BinderProxy类的jni方法,gBinderProxyOffsets保存了BinderProxy的构造方法,sendDeathNotice(),mObject,mSelf,mOrgue信息。

BinderProxy类在Binder类中,是本地IBinder对象的java代理,由本地javaObjectforIBinder函数分配构造。BinderProxy类中还有一个静态不可变的内部类ProxyMap,将BinderProxy作为弱引用对象放入ArrayList集合。

这里也是建立了BinderProxy类在Native层与framework层之间相互调用的桥梁。

注册服务

SM.addService

public static void addService(String name, IBinder service, boolean allowIsolated) {
    try {
        //先获取SMP对象,则执行注册服务操作
        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;
    }
    
    //这里调用了ServiceManagerNative获取sServiceManager
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

采用单例模式获取ServiceManager getIServiceManager()返回的是ServiceManagerProxy对象

getContextObject

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

BinderInternal.java中有一个native方法getContextObject(),JNI调用执行上述方法。

这里有个熟悉的ProcessState::self()->getContextObject()在分析获取ServiceManager的时候调用过,就相当于是new BpBinder(0)

javaObjectForIBinder

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

    if (val->checkSubclass(&gBinderOffsets)) { //返回false
        jobject object = static_cast(val.get())->object();
        return object;
    }

    AutoMutex _l(mProxyLock);

    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) { //第一次object为null
        jobject res = jniGetReferent(env, object);
        if (res != NULL) {
            return res;
        }
        android_atomic_dec(&gNumProxyRefs);
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }

    //创建BinderProxy对象
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        //BinderProxy.mObject成员变量记录BpBinder对象
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);

        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        //将BinderProxy对象信息附加到BpBinder的成员变量mObjects中
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);

        sp drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        //BinderProxy.mOrgue成员变量记录死亡通知对象
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(drl.get()));

        android_atomic_inc(&gNumProxyRefs);
        incRefsCreated(env);
    }
    return object;
}

这个方法中出现了重要的BinderPrody对象。根据BpBinder(c++)生成BinderProxy(java)对象,并把BpBinder对象地址保存到BinderProxy.mObject成员变量。可以知道:

ServiceManagerNative.asInterface(BinderInternal.getContextObject())

等价于

ServiceManagerNative.asInterface(new BinderProxy());

SMN.asInterface

 static public IServiceManager asInterface(IBinder obj)
{
    if (obj == null) { //obj为BpBinder
        return null;
    }
    //由于obj为BpBinder,该方法默认返回null
    IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    return new ServiceManagerProxy(obj);
}

这里可以知道ServiceManagerNative.asInterface(new BinderProxy())等价于ServiceManagerProxy(new BinderProxy)

ServiceManagerProxy初始化

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
}

mRemote为BinderProxy对象,该BinderProxy对象对应于BpBinder(0),其作为Binder代理端,指向Native层大管家SerivceManager。

可以说ServiceManager.getIServiceManager == new ServiceManagerProxy(new BinderProxy()),也就意味着getIServiceManager.addService == ServiceManagerProxy.addService()

总结

  1. framework层的ServiceManager的调用实际上是交给了ServiceManagerProxy的成员变量BinderProxy;
  2. BinderProxy通过jni方式,最终会调用BpBinder对象。

说明上层binder架构的核心功能依赖native架构。

SMP.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
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

这段代码有一种很熟悉的感觉,在写aidl的文件中Proxy代理类中就这样包装数据,并调用transact()方法发送数据。

writeStrongBinder

public writeStrongBinder(IBinder val){
    //此处为Native调用
    nativewriteStrongBinder(mNativePtr, val);
}

android_os_Parcel_writeStrongBinder

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) {
    //将java层Parcel转换为native层Parcel
    Parcel* parcel = reinterpret_cast(nativePtr);
    if (parcel != NULL) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}

ibinderForJavaObject

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

    //Java层的Binder对象
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
    //Java层的BinderProxy对象
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
    return NULL;
}

根据Binder(java)生成JavaBBinderHolder(C++)对象。主要工作是创建JavaBBinderHolder对象,并把JavaBBinderHolder对象地址保存到Binder.mObject成员变量。

JavaBBinderHolder.get()

sp get(JNIEnv* env, jobject obj)
{
    AutoMutex _l(mLock);
    sp b = mBinder.promote();
    if (b == NULL) {
        //首次进来,创建JavaBBinder对象
        b = new JavaBBinder(env, obj);
        mBinder = b;
    }
    return b;
}

JavaBBinderHolder有一个成员变量mBinder,保存当前创建的JavaBBinder对象,这是一个弱引用类型的,可能会被垃圾回收器给回收,所以每次使用前都需要判断是否存在。

JavaBBinder初始化

JavaBBinder(JNIEnv* env, jobject object)
    : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
    android_atomic_inc(&gNumLocalRefs);
    incRefsCreated(env);
}

创建JavaBBinder,该对象继承于BBinder对象。

data.writeStrongBinder(service)等价于parcel->writeStrongBinder(new JavaBinder(env,obj));

writeStrongBinder(C++)

status_t Parcel::writeStrongBinder(const sp& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}

flatten_binder

status_t flatten_binder(const sp& /*proc*/,
    const sp& binder, Parcel* out)
{
    flat_binder_object obj;

    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE; //远程Binder
            obj.binder = 0;
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            obj.type = BINDER_TYPE_BINDER; //本地Binder,进入该分支
            obj.binder = reinterpret_cast(local->getWeakRefs());
            obj.cookie = reinterpret_cast(local);
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;  //本地Binder
        obj.binder = 0;
        obj.cookie = 0;
    }
    
    return finish_flatten_binder(binder, obj, out);
}

将Binder对象扁平化,转成flat_binder_object对象。

  • 对于Binder实体,则cookie记录Binder实体指针;
  • 对于Binder代理,则用handle记录Binder代理的句柄。

BinderProxy.transact

回到mRemote.transact方法

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    //用于检测Parcel大小是否大于800k
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
    return transactNative(code, data, reply, flags);
}

mRemote是BinderProxy。transactNative经过jni调用,进入下面的方法

android_os_BinderProxy_transact

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
    jint code, jobject dataObj, jobject replyObj, jint flags)
{
    ...
    //java Parcel转为native Parcel
    Parcel* data = parcelForJavaObject(env, dataObj);
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ...

    //gBinderProxyOffsets.mObject中保存的是new BpBinder(0)对象
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ...

    //此处便是BpBinder::transact(), 经过native层,进入Binder驱动程序
    status_t err = target->transact(code, *data, reply, flags);
    ...
    return JNI_FALSE;
}

java层的BinderProxy.transact()最终交由Native层的BpBinder::transact()完成。

小结

addService核心过程:

public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
    ...
    Parcel data = Parcel.obtain(); //此处还需要将java层的Parcel转为Native层的Parcel
    data->writeStrongBinder(new JavaBBinder(env, obj));
    BpBinder::transact(ADD_SERVICE_TRANSACTION, *data, reply, 0); //与Binder驱动交互
    ...
}

注册服务过程就是通过BpBinder来发送ADD_SERVICE_TRANSACTION命令,与实现与binder驱动进行数据交互。

参考资料

Binder系列7——framework层分析

你可能感兴趣的:(IPC机制(六)——Binder原理分析(二))