美文网首页Android
我终于找到一篇“Java层的ServiceManager和Nat

我终于找到一篇“Java层的ServiceManager和Nat

作者: Fakecoder_Sunis | 来源:发表于2018-04-24 14:45 被阅读0次

    Java层ServiceManager和Native层ServiceManager的关系。
    转自 这里。感谢有牛人写出这样的文章来工参考学习。不过,别人的话我记不住,早晚有一天,我自己重新写一次:)

    Java层Binder的初始化过程

    Binder最终是要和它的驱动打交道,Java层要调Linux内核层的东西必然要通过native方法,而对于android的系统服务,native和java的对应,总会有一个注册过程,先看这个注册是在哪实现的

    JNI Binder的注册

    Zygote在启动时:

    app_main.cpp
    int main(int argc, char* const argv[])
    {
        ......
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
        ......
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        }
        ......
    }
    

    AppRuntime是AndroidRuntime的子类,它本身没有覆盖start方法,所以要去看AndroidRuntime类中的start方法

    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
        ......
        /*
         * Register android functions.
         */
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
        ......
    }
    
    /*
     * Register android native functions with the VM.
     */
    /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
    {
        ......
        if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
            env->PopLocalFrame(NULL);
            return -1;
        }
        ......
    }
    

    gRegJNI是个数组:

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

    REG_JNI是一个宏定义

    #ifdef NDEBUG
        #define REG_JNI(name)      { name }
        struct RegJNIRec {
            int (*mProc)(JNIEnv*);
        };
    #else
        #define REG_JNI(name)      { name, #name }
        struct RegJNIRec {
            int (*mProc)(JNIEnv*);
            const char* mName;
        };
    #endif
    

    gRegJNI是一个RegJNIRec的数组,所以gRegJNI的定义就变成了这样:

    static const RegJNIRec gRegJNI[] = {
        ......
        { register_android_os_Binder },
        ......
    };
    

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

    就是循环调用gRegJNI数组中的函数,这时register_android_os_Binder(env)就被调用了。

    register_android_os_Binder在AndroidRuntime.cpp中被声明为extern:

    extern int register_android_os_Binder(JNIEnv* env);
    

    实现它的地方是在android_util_Binder.cpp中:

    int register_android_os_Binder(JNIEnv* env)
    {
        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;
        ......
        return 0;
    }
    
    

    从名字上看,它要关联3个Java的类,分别是Binder, BinderInternal和BinderProxy,一个一个看来:

    const char* const kBinderPathName = "android/os/Binder";
    
    static int int_register_android_os_Binder(JNIEnv* env)
    {
        jclass clazz = FindClassOrDie(env, kBinderPathName);
    
        gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
        gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
        gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
    
        return RegisterMethodsOrDie(
            env, kBinderPathName,
            gBinderMethods, NELEM(gBinderMethods));
    }
    

    关联了android.os.Binder类,并会用到该类的mExecTransact域和execTransact方法,将其保存到gBinderOffsets对象中,也就意味着native会将某值保存到mExecTransact中,也会回调execTransact方法。

    const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
    
    static int int_register_android_os_BinderInternal(JNIEnv* env)
    {
        jclass clazz = FindClassOrDie(env, kBinderInternalPathName);
    
        gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
        gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
    
        return RegisterMethodsOrDie(
            env, kBinderInternalPathName,
            gBinderInternalMethods, NELEM(gBinderInternalMethods));
    }
    

    关联了java的com.android.internal.os.BinderInternal类,保存了其forceBinderGc方法。

    const char* const kBinderProxyPathName = "android/os/BinderProxy";
    
    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");
    
        clazz = FindClassOrDie(env, "java/lang/Class");
        gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
    
        return RegisterMethodsOrDie(
            env, kBinderProxyPathName,
            gBinderProxyMethods, NELEM(gBinderProxyMethods));
    }
    

    这个方法比较长,保存的Java的东西也比较多,值得注意的是,它还保存了BinderProxy的构造函数,也就是说它可能会主动new一个BinderProxy实例出来。

    看到目前为止,native的Binder要对应到Java的3个类中,分别是android.os.Binder,com.android.internal.os.BinderInternal和android.os.BinderProxy。为了方便阅读,将它们的对应关系以类图的形式总结下:

    这里写图片描述

    将Java层的服务注册到ServiceManager中的过程

    我们知道,native层的Binder有Bn和Bp之说,Bn应该是Binder Native的缩写,就是本地实现Binder的意思也可以说是C/S中的S,Bp是Binder Proxy的缩写,相当于C。

    以PackageManagerService为例:

        public static PackageManagerService main(Context 
            ......
            PackageManagerService m = new PackageManagerService(context, installer,
                    factoryTest, onlyCore);
            ......
            ServiceManager.addService("package", m);
            return m;
        }
    
        public static void addService(String name, IBinder service) {
            try {
                getIServiceManager().addService(name, service, false);
            } catch (RemoteException e) {
                Log.e(TAG, "error in addService", e);
            }
        }
    

    getIServiceManager返回的是一个IServiceManager类,且是个单例,最后调用的就是

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

    以上代码带来 三个问题,一个是BinderInternal.getContextObject(),一个是ServiceManagerNative.asInterface,另一个是addService的作用:

    BinderInternal.getContextObject()的实质

    ServiceManagerNative.asInterface中的参数是BinderInternal.getContextObject(),看它是native方法,对应的native代码就在刚刚看到的android_util_Binder.cpp文件中:

    static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
    {
        // 是一个BpBinder
        sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
        return javaObjectForIBinder(env, b);
    }
    
    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?
        // 1
        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);
        }
    
        //2
        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.
            //3
            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));
            ......
            // Note that a new object reference has been created.
            //4
            android_atomic_inc(&gNumProxyRefs);
            incRefsCreated(env);
        }
    
        return object;
    }
    
    1. 首先判断下和Java层关联的Native层的BpBinder是否存在,如果存在,删除。
    2. 接着创建一个Java层的BinderProxy实例。
    3. 将Native层的BpBinder指针保存到java BinderProxy实例的mObject字段中,这样通过BinderProxy的mObject字段就可以操作Native层的BpBinder了。
    4. 原子增加gNumProxyRefs和gNumRefsCreated的数量,当gNumRefsCreated的值超过200,将会调用BinderInternal的forceBinderGc方法。

    总结下:

    • 创建了一个Native层的BpBinder;
    • 将BpBinder的指针保存到BinderProxy的mObject,而BpBinder的通信对象就是Native的ServiceManager,这为Java和Native的ServiceManager的通信埋下了伏笔。
    • 可以将BinderProxy说成Java层的Bp端。

    ServiceManagerNative.asInterface的作用

        static public IServiceManager asInterface(IBinder obj)
        {
            if (obj == null) {
                return null;
            }
            //1
            IServiceManager in =
                (IServiceManager)obj.queryLocalInterface(descriptor);
            if (in != null) {
                return in;
            }
    
            //2
            return new ServiceManagerProxy(obj);
        }
    
    1. obj是Native实例化的BinderProxy对象,BinderProxy的代码在Binder.java中,和Binder位于同一个文件中。queryLocalInterface的返回值为null。
    2. 实例化一个ServiceManagerProxy对象,该实例中有一个IBinder类型的mRemote字段,该字段保存BinderProxy实例。
        public ServiceManagerProxy(IBinder remote) {
            mRemote = remote;
        }
    

    总结:

    • ServiceManagerNative.asInterface返回的是ServiceManagerProxy的实例,该实例实现IServiceManager的接口。
    • ServiceManagerProxy中通过mRemote字段保存了BinderProxy,也就是Java层的Bp端。

    addService的作用

    有上分析,当调用ServiceManager.addService时,实际上调用的是ServiceManagerProxy类中的addService,ServiceManagerProxy类位于ServiceManagerNative.java文件中。

        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);
            //1
            mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
            reply.recycle();
            data.recycle();
        }
    
    1. mRemote即为BinderProxy,它会调用transactNative,transactNative是个native方法,接着看这个方法。
    static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        //1
        IBinder* target = (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
        if (target == NULL) {
            jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
            return JNI_FALSE;
        }
    
        //2
        status_t err = target->transact(code, *data, reply, flags);
        ......
        return JNI_FALSE;
    }
    
    1. 取出保存在BinderProxy中的BpBinder对象的指针
    2. 向Native层的ServiceManager发送请求

    总结:

    • Java层调用ServiceManger.addService后,最终是向Native层的ServiceManager请求增加服务的。
    • Native层的ServiceManager是只有一个的,而java层的ServiceManager相对于Native的ServiceManager也只是个C端,这样,不管是通过Native add service还是通过java add service,整个Android都可以拿到这个service的Binder。

    Java Service端的Bp在哪里

    这时候还有个疑问,当调用ServiceManager.addService时传入的Service应该对应到Native的BnBinder啊,现在对应关系如何体现呢?这个关系要重看下addService了。

    addService第二个参数的类型是IBinder,它是个接口,而它的实现类是Binder,java上层能调用addService添加服务时,所有的实例都是Binder,根据java的规则,只要实例化,其父类的相应的构造函数必被调用:

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

    init()是native方法,其实现在android_util_Binder.cpp中:

    static void android_os_Binder_init(JNIEnv* env, jobject obj)
    {
        JavaBBinderHolder* jbh = new JavaBBinderHolder();
        ...
        env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
    }
    

    new一个native层的JavaBBinderHolder,并将其保存到Binder的mObject中。注意哦,虽然native层的gBinderOffsets.mObject是个static的,但java层的Binder的mObject可不是static的哦,就是说每个Binder实例都有一个Native的JavaBBinderHolder对象指针。

    JavaBBinderHolder类的声明如下:

    class JavaBBinderHolder : public RefBase
    {
    }
    

    没有继承BBinder,还是没发现作为Bn端的踪影,需要再review下前面的流程,看下ServiceManagerProxy添加服务时发生了什么:

        public void addService(String name, IBinder service, boolean allowIsolated)
                throws RemoteException {
            Parcel data = Parcel.obtain();
            ......
            data.writeStrongBinder(service);
            ......
        }
    

    writeStrongBinder值得怀疑

    writeStrongBinder发生了什么

    Parcel的这个函数如下:

        public final void writeStrongBinder(IBinder val) {
            nativeWriteStrongBinder(mNativePtr, val);
        }
    

    nativeWriteStrongBinder的实现在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;
    
        if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
            JavaBBinderHolder* jbh = (JavaBBinderHolder*)
                env->GetLongField(obj, gBinderOffsets.mObject);
            return jbh != NULL ? jbh->get(env, obj) : NULL;
        }
    
        if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
            return (IBinder*)
                env->GetLongField(obj, gBinderProxyOffsets.mObject);
        }
    
        ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
        return NULL;
    }
    

    传入的obj是Binder实例,所以刚刚创建的JavaBBinderHolder的get函数会被调用:

        sp<JavaBBinder> get(JNIEnv* env, jobject obj)
        {
            AutoMutex _l(mLock);
            sp<JavaBBinder> b = mBinder.promote();
            if (b == NULL) {
                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;
        }
    

    返回的是JavaBBinder实例,

    class JavaBBinder : public BBinder
    {
    }
    

    JavaBBinder继承了BBinder,所以最终添加到Native ServiceManager中的是这个对象,总结下它们的类图:

    这里写图片描述

    Java层的Binder对象拥有Native JavaBBinderHolder对象的指针,JavaBBinderHolder有JavaBBinder的,而JavaBBinder又有Java层Binder的对象。

    相关文章

      网友评论

        本文标题:我终于找到一篇“Java层的ServiceManager和Nat

        本文链接:https://www.haomeiwen.com/subject/wmljlftx.html