Android Binder 框架层详解

Posted Jason_Wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Binder 框架层详解相关的知识,希望对你有一定的参考价值。

在了解完binder在native层以及驱动层的基本流程之后(参考Android如何注册服务到ServiceManager; Android 系统服务管家servicemanager启动过程详解 ),接下来这篇文章我们就来分析下binder在framework层(Java层)的具体原理与实现,重点围绕Java层如何添加服务到系统中这一主题展开。这里会谈到以下几个方面的问题:

  • binder在Java层的具体架构与实现
  • binder在Java层的ServiceManager又是如何实现
  • android中如何加载注册binder相关的JNI方法

binder源码涉及面广,错误之处难以避免,欢迎各位批评指正

binder在Java层的具体实现

下图为Android框架层ServiceManager的结构简图。可以看到,框架层的ServiceManager主要是为上层应用或服务提供一个统一的接口,用于向系统注册、查询或者获取服务,在另一端Binder以及BinderProxy则通过JNI方法调用native层的方法,以此来使用binder底层提供的接口。

  • ServiceManager是一个不可初始化的类,其向外提供了addService(添加服务)、getService(获取服务)、checkService(检查服务)、listService列举所有系统服务等接口,并返回系统服务相关的IBinder接口;
  • IServiceManager是一个接口,ServiceManager正是通过该接口的实现ServiceManagerProxy来调用native层的代码的;
  • ServiceManagerProxy代理对象有一个mRemote变量,该变量实际是一个BinderProxy实例,通过BinderProxy就可以将Java层的RPC请求发送给native层,进而传递给binder驱动;
  • IBinder是RPC调用的一个抽象接口,代表了一个远程对象,通过该接口,我们可以向服务端发送RPC请求,该接口的核心函数是transact:

    public boolean transact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException;

这是一个同步调用,只有当服务端返回时,该函数才会返回结果。

源码(以下分析均基于Android N7.0): /android/frameworks/base/core/java/android/os/ServiceManager.java

接下来,就来看看上层如何调用ServiceManager接口将系统服务注册到系统中的?

注册服务到servicemanager

在系统服务进程SystemServer启动后,会注册很多服务,包括系统核心服务以及其他非系统服务:


    private void run() 
        ....
        // 启动服务
        try 
            //启动自举服务:PowerManager,DisplayManger 等等
            startBootstrapServices();
            //启动系统核心服务
            startCoreServices();
            //启动其他服务:Vibrator,TelecomRegistry,NetworkConnectivity...
            startOtherServices();
         catch (Throwable ex) 
            throw ex;
         finally 
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        

        ....
    


    private void startOtherServices() 
        ....
        telephonyRegistry = new TelephonyRegistry(context);
        ServiceManager.addService("telephony.registry", telephonyRegistry);
        ....
        vibrator = new VibratorService(context);
        ServiceManager.addService("vibrator", vibrator);
        ....
    

代码路径:/android/frameworks/base/services/java/com/android/server/SystemServer.java

调用ServiceManager方法addService:


    public static void addService(String name, IBinder service) 
        try 
            getIServiceManager().addService(name, service, false);
         catch (RemoteException e) 
            Log.e(TAG, "error in addService", e);
        
    


    private static IServiceManager sServiceManager;
    // 获取IServiceManager接口
    private static IServiceManager getIServiceManager() 
        if (sServiceManager != null) 
            return sServiceManager;
        

        // 获取servicemanager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    

这里,BinderInternal.getContextObject()究竟返回的是什么了?进去一看,发现getContextObject()是一个本地化方法,需要通过JNI来调用native的代码:


    // 一个本地化方法
    public static final native IBinder getContextObject();

直接搜索 getContextObject,发现在android_util_Binder.cpp这个JNI文件中,定义了相应的JNI函数:


    static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
    
        // 获取serviemanager对应的binder对象: BpBinder(0)
        sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
        // 这里返回的是什么了?
        return javaObjectForIBinder(env, b);
    


    jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
    
        ....
        // 新建一个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));
            val->attachObject(&gBinderProxyOffsets, refObject,
                    jnienv_to_javavm(env), proxy_cleanup);

            // Also remember the death recipients registered on this proxy
            sp<DeathRecipientList> drl = new DeathRecipientList;
            drl->incStrong((void*)javaObjectForIBinder);
            env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

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

        return object;
    
    // 保存了BinderProxy类的信息
    static struct binderproxy_offsets_t
    
        // Class state.
        jclass mClass;
        jmethodID mConstructor;
        jmethodID mSendDeathNotice;

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

     gBinderProxyOffsets;

从这里,我们大概可以判断出,javaObjectForIBinder实际返回的是一个Java对象BinderProxy,该对象有一个成员变量mObject保存了一个本地的BpBinder引用(参考Android如何注册服务到ServiceManager)。那么,与BinderProxy紧密相关的结构体变量gBinderProxyOffsets又是在何时被初始化的,这个疑问留到下一节“binder JNI方法的初始化”再来分析。暂时,我们知道BinderInternal.getContextObject()返回的是一个servicemanager对应的BinderProxy。这样


    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

就等价于: sServiceManager = ServiceManagerNative.asInterface(new BinderProxy());,接着看一看asInterface这个方法:


    /**
     * Cast a Binder object into a service manager interface, generating
     * a proxy if needed.
     */
    static public IServiceManager asInterface(IBinder obj)
    
        if (obj == null) 
            return null;
        
        // BinderProxy直接返回null
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) 
            return in;
        
        // 新建一个ServiceManagerProxy(BindProxy)对象
        return new ServiceManagerProxy(obj);
    

    // ServiceManagerProxy构造函数,将BinderProxy实例保存到mRemote中
    public ServiceManagerProxy(IBinder remote) 
        mRemote = remote;
    

源码: /android/frameworks/base/core/java/android/os/ServiceManagerNative.java

到这里,不难看出,调用ServiceManager.addService()实际调用的就是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);
        // 调用BinderProxy的transact,发送RPC请求到servicemanager
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    

    // BinderProxy
    final class BinderProxy implements IBinder 
        public IInterface queryLocalInterface(String descriptor) 
            return null;
        
        ....
        public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException 
            Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
            ....
            return transactNative(code, data, reply, flags);
        
        //调用JNI方法发送RPC请求
        public native boolean transactNative(int code, Parcel data, Parcel reply,int flags) throws RemoteException;
    

那么,transactNative又是如何调用到native层的方法的了?同样在android_util_Binder.cpp中定义了BinderProxy相关的JNI方法,其中transactNative对应的JNI方法是android_os_BinderProxy_transact


    static const JNINativeMethod gBinderProxyMethods[] = 
         /* name, signature, funcPtr */
        "pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder,
        "isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive,
        "getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor,
        "transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact,
        "linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath,
        "unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath,
        "destroy",             "()V", (void*)android_os_BinderProxy_destroy,
    ;


    static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
            jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
    
        if (dataObj == NULL) 
            jniThrowNullPointerException(env, NULL);
            return JNI_FALSE;
        
        // gBinderProxyOffsets.mObject 就是指向servicemanger的远程对BpBinder(0)
        IBinder* target = (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
        if (target == NULL) 
            jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
            return JNI_FALSE;
        
        ....
        // BpBinder->transact(...)
        status_t err = target->transact(code, *data, reply, flags);
        ....
    

到这了BpBinder以后,就与之前的一篇文章Android如何注册服务到ServiceManager所讲的流程完全一样了。

binder JNI方法的初始化

在上文中提到,BinderInternal.getContextObject()返回的是一个BinderProxy对象,同时该对象会引用一个native层的BpBinder实例。那么,Android究竟是如何初始化JNI?又是如何根据gBinderProxyOffsets这个结构体变量来构造一个Java对象BinderProxy的了?

在Android启动过程中(参考Android开机流程,init进程通过init.zygotexxx.rc来启动zygote系统服务用于加载虚拟机实例(系统只有一个zygote进程,但是不同进程会有不同的VM实例,不同的VM实例会通过zygote来共享一些共有的数据):


    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
        class main
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart audioserver
        onrestart restart cameraserver
        onrestart restart media
        onrestart restart netd

找到app_process进程的代码入口:


    int main(int argc, char* const argv[])
    
        //获取runtime实例
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
        // ignore argv[0]
        argc--;
        argv++;

        bool zygote = false;
        bool startSystemServer = false;

        ++i;  // Skip unused "parent dir" argument.
        while (i < argc) 
            const char* arg = argv[i++];
            if (strcmp(arg, "--zygote") == 0) 
                zygote = true;
                niceName = ZYGOTE_NICE_NAME;
             else if (strcmp(arg, "--start-system-server") == 0) 
                startSystemServer = true;
                
             

            if (startSystemServer) 
                args.add(String8("start-system-server"));
            
            ....
        

        ....

        // 创建第一个Dalvik VM实例,启动ZygoteInit进程
        if (zygote) 
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
         else if (className) 
            runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
        
        ....
    

源码: /android/frameworks/base/cmds/app_process/app_main.cpp


    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    
        ....
        //初始化VM参数,创建VM实例
        JniInvocation jni_invocation;
        jni_invocation.Init(NULL);
        JNIEnv* env;
        if (startVm(&mJavaVM, &env, zygote) != 0) 
            return;
        
        onVmCreated(env);

        // 注册JNI函数
        if (startReg(env) < 0) 
            ALOGE("Unable to register all android natives\\n");
            return;
        

        ....

        //启动zygote进程:新建一个SystemServer进程,加载系统基础类与库
        char* slashClassName = toSlashClassName(className);
        jclass startClass = env->FindClass(slashClassName);
        if (startClass == NULL) 
            ALOGE("JavaVM unable to locate class '%s'\\n", slashClassName);
            /* keep going */
         else 
            jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");
            if (startMeth == NULL) 
                ALOGE("JavaVM unable to find main() in '%s'\\n", className);
             else 
                //调用ZygoteInit的main函数
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
            ....
        
        ....
    

系统JNI方法都是在函数startReg(env)中注册上的:


    /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
    
        ....
        env->PushLocalFrame(200);
        //注册所有的JNI函数到系统中
        if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) 
            env->PopLocalFrame(NULL);
            return -1;
        
        env->PopLocalFrame(NULL);

        return 0;
    

    //gRegJni是系统JNI函数指针结构体数组
    #define REG_JNI(name)       name 
    struct RegJNIRec 
        int (*mProc)(JNIEnv*);
    ;

    static const RegJNIRec gRegJNI[] = 
        ....
        REG_JNI(register_android_os_Process),
        REG_JNI(register_android_os_SystemProperties),
        //注册binder相关的JNI函数
        REG_JNI(register_android_os_Binder),
        REG_JNI(register_android_os_Parcel),
        REG_JNI(register_android_nio_utils),
        ....
    ;

找到register_android_os_Binder函数所在源码:android_util_Binder.cpp,在这个函数里,会注册所有和Binder框架层相关的JNI函数:


    int register_android_os_Binder(JNIEnv* env)
    
        //注册Binder.java对应的JNI
        if (int_register_android_os_Binder(env) < 0)
            return -1;
        //注册BinderInternal.java对应的JNI
        if (int_register_android_os_BinderInternal(env) < 0)
            return -1;
        //注册BinderProxy.java对应的JNI
        if (int_register_android_os_BinderProxy(env) < 0)
            return -1;
        ....

        return 0;
    

正是在int_register_android_os_BinderProxy这个函数里,初始化了结构体变量gBinderProxyOffsets,其中mClass指向一个全局的BinderProxy引用,mConstructor指向BinderProxy的构造函数,而mObject初始化为BinderProxy的成员变量的ID值。这样初始化后,我们就可以使用gBinderProxyOffsets直接返回一个BinderProxy实例了。


    const char* const kBinderProxyPathName = "android/os/BinderProxy";

    static int int_register_android_os_BinderProxy(JNIEnv* env)
    
        //查找BinderProxy类
        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");
        ....
        //注册BinderProxy相关的JNI
        return RegisterMethodsOrDie(
            env, kBinderProxyPathName,
            gBinderProxyMethods, NELEM(gBinderProxyMethods));
    

至此,我们对Binder框架层也有了一个比较深入的理解与认识。这里,对如何在框架层添加系统服务的流程做一个简单的总结:

  1. 调用ServiceManageraddService()接口时,getIServiceManager返回一个ServiceManagerProxy对象;
  2. 调用ServiceManagerProxyaddService()接口;
  3. ServiceManagerProxy中有一个mRomote成员变量指向一个BinderProxy对象,它是本地servicemanager的远程代理;
  4. 通过JNI接口transactNative()发送数据到libbinder;

以上是关于Android Binder 框架层详解的主要内容,如果未能解决你的问题,请参考以下文章

[gitbook] Android框架分析系列之Android Binder详解

[gitbook] Android框架分析系列之Android Binder详解

Android binder 机制驱动核心源码详解

Android-Binder进程间通讯机制-多图详解

Android-binder通信详解

android binder深入分析之承上启下的native层