Java層的ServiceManager和Native層的ServiceManager的對應過程

幾天前一個同事問Java層的Binder和Java層的ServiceManager和C++層的ServiceManager是如何對應起來的,竟然一時語噻,一段時間不關注就會感到陌生啊,現在再總結一下,只寫Java層的,C++層的不寫,C++ Binder的知識需掌握,java和native的基本概念及對應關係不講。

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的對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章