Android Binder分析4:Java service的注册

Android Binder分析四:Java service的注册

这一章通过WifiService来分析一下在Java framework中如何注册Service,在分析注册WifiService之前,先来看一下WifiService相关的类图:

Android Binder分析4:Java service的注册

下面是我们以前分析过的WifiService的注册代码:

               try {
                    Slog.i(TAG, "Wi-Fi Service");
                    wifi = new WifiService(context);
                    ServiceManager.addService(Context.WIFI_SERVICE, wifi);
                } catch (Throwable e) {
                    reportWtf("starting Wi-Fi Service", e);
                }

这里首先构造一个WifiService对象,在构造WifiService对象时,我们前面已经看过的构造函数了,这里主要来看一下它的两个父类的构造函数:

        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

    public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }

IWifiManager.Stub的构造函数中调用attachInterface将一个interface与binder联系起来,方便后面查找。

    public Binder() {
        init();
    }

Binder的构造函数主要就是调用init去做初始化的工作,init的实现在android_util_Binder.cpp中,我们后面再来分析。

这里调用ServiceManager的addService方法,第一个参数Context.WIFI_SERVICE是"wifi"字串;第二个参数是WifiService对象,WifiService是继承于Binder的。来看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);
        }
    }

首先调用getIServiceManager来获取一个ServiceManagerProxy对象,如下:

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

下面先来看一下Java层的ServiceManager相关的文件结构:

Android Binder分析4:Java service的注册


在分析BinderInternal.getContextObject()前,我们先来分析一下android_util_Binder.cpp这个文件,它是Java层的binder和Native层的binder中间的桥梁。android_util_Binder.cpp的初始化函数是register_android_os_Binder,它在AndroidRuntime初始化时被加载执行。在register_android_os_Binder方法中,又分为三个步骤,第一步映射Java层的Binder类,并注册其中的Native函数;第二步映射Java层的BinderInternal类,并注册其中的Native函数;第三步映射Java层的BinderProxy类,并注册其中的Native函数:

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;

    jclass clazz;

    clazz = env->FindClass("android/util/Log");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log");
    gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gLogOffsets.mLogE = env->GetStaticMethodID(
        clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
    assert(gLogOffsets.mLogE);

    clazz = env->FindClass("android/os/ParcelFileDescriptor");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
    gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gParcelFileDescriptorOffsets.mConstructor
        = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");

    clazz = env->FindClass("android/os/StrictMode");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
    gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gStrictModeCallbackOffsets.mCallback = env->GetStaticMethodID(
        clazz, "onBinderStrictModePolicyChange", "(I)V");
    LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
                 "Unable to find strict mode callback.");

    return 0;
}

首先来看int_register_android_os_Binder方法:

static int int_register_android_os_Binder(JNIEnv* env)
{
    jclass clazz;

    clazz = env->FindClass(kBinderPathName);
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");

    gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
    gBinderOffsets.mExecTransact
        = env->GetMethodID(clazz, "execTransact", "(IIII)Z");
    assert(gBinderOffsets.mExecTransact);

    gBinderOffsets.mObject
        = env->GetFieldID(clazz, "mObject", "I");
    assert(gBinderOffsets.mObject);

    return AndroidRuntime::registerNativeMethods(
        env, kBinderPathName,
        gBinderMethods, NELEM(gBinderMethods));
}
首先通过JNI的FindClass把Binder.class加载进来,然后在gBinderOffsets保存Binder.class的引用和Binder的execTransact函数ID,通过mObject保存Binder中mObject变量的ID,这个变量用于以后存储JNI层JavaBBinderHolder的地址。最后调用registerNativeMethods将Java层的函数和Native层的函数建立好映射关系。int_register_android_os_BinderInternal和int_register_android_os_BinderProxy与int_register_android_os_Binder实现差不多,通过上面三个函数,我们可以在JNI层看到下面的数据关系:

结构体 变量名 解释
gBinderOffsets mClass 保存Binder.class的ref
  mExecTransact 保存Binder.class的execTransact函数ID
  mObject 保存Binder.class的mObject成员ID,实际保存JavaBBinderHolder的地址
gBinderInternalOffsets mClass 保存BinderInternal.class的ref
  mForceGc 保存BinderInternal.class的forceBinderGc函数ID
gBinderProxyOffsets mClass 保存BinderProxy.class的ref
  mConstructor 保存BinderProxy.class的init函数ID
  mSendDeathNotice 保存BinderProxy.class的sendDeathNotice函数ID
  mObject 保存BinderProxy.class的mObject成员ID,实际保存BpBinder地址
  mSelf 保存BinderProxy.class的mSelf成员ID,用于注册将BpBinder和BinderProxy绑定
  mOrgue 保存BinderProxy.class的mOrgue成员ID,实际保存DeathRecipientList地址


在register_android_os_Binder函数的后面,主要是保存Log、ParcelFileDescriptor和StrictMode工具类的一些函数和变量地址。回到getIServiceManager()方法中,BinderInternal.getContextObject()这个函数,它透过JNI调用,实现在android_util_Binder.cpp中的
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

ProcessState::self()->getContextObject(NULL)我们前面分析过,它就是返回BpBinder(0),来看javaObjectForIBinder方法:

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

    if (val->checkSubclass(&gBinderOffsets)) {
        return object;
    }

    AutoMutex _l(mProxyLock);

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

    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());
        val->incStrong((void*)javaObjectForIBinder);

        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);

        sp<DeathRecipientList> drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        env->SetIntField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jint>(drl.get()));

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

    return object;
}

在binder.cpp中,checkSubclass默认返回false;在BpBinder中它维护一个KeyedVector来保存当前BpBinder与BinderProxy之间的映射关系,如果前面有绑定过BinderProxy与BpBinder,后面就可以直接通过findObject找到前面绑定的BinderProxy,从而可以获得BpBinder。这里假设是第一次调用,所以会先创建一个BinderProxy对象,然后设置BinderProxy对象的mObject为BpBinder(0)的内存地址;获取BinderProxy对象的mSelf这个WeakReference对象,并调用BpBinder的attachObject将BinderProxy与BpBinder绑定起来,并将mOrgue设置为DeathRecipientList对象的地址。然后返回BinderProxy对象给getIServiceManager()方法。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);
    }

因为这里的obj就是BinderProxy对象,它的queryLocalInterface返回NULL,所以后面会创建一个ServiceManagerProxy对象。把上面的getIServiceManager就可以改写为:

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = new ServiceManagerProxy(BinderProxy);
        return sServiceManager;
    }

调用getIServiceManager().addService方法实际上就是调用ServiceManagerProxy的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);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }

这里首先申请两个Parcel对象,我们来简单的看一下Parcel的obtain和recycle方法。在Java层的Parcel,维护一个Parcel pool,当用户需要申请Parcel时,就调用Parcel.obtain,当用户用完时,需要调用Parcel.recycle方法让它回到pool中以便后面再使用。

    public static Parcel obtain() {
        final Parcel[] pool = sOwnedPool;
        synchronized (pool) {
            Parcel p;
            for (int i=0; i<POOL_SIZE; i++) {
                p = pool[i];
                if (p != null) {
                    pool[i] = null;
                    if (DEBUG_RECYCLE) {
                        p.mStack = new RuntimeException();
                    }
                    return p;
                }
            }
        }
        return new Parcel(0);
    }

    public final void recycle() {
        if (DEBUG_RECYCLE) mStack = null;
        freeBuffer();

        final Parcel[] pool;
        if (mOwnsNativeParcelObject) {
            pool = sOwnedPool;
        } else {
            mNativePtr = 0;
            pool = sHolderPool;
        }

        synchronized (pool) {
            for (int i=0; i<POOL_SIZE; i++) {
                if (pool[i] == null) {
                    pool[i] = this;
                    return;
                }
            }
        }
    }

POOL_SIZE为6,表示在一个进程中,最多可以同时申请6个Parcel对象。当第一次申请时,所有的sOwnedPool都为NULL,所以创建Parcel(0)来分配Native层的Parcel对象。

    private Parcel(int nativePtr) {
        if (DEBUG_RECYCLE) {
            mStack = new RuntimeException();
        }
        //Log.i(TAG, "Initializing obj=0x" + Integer.toHexString(obj), mStack);
        init(nativePtr);
    }

    private void init(int nativePtr) {
        if (nativePtr != 0) {
            mNativePtr = nativePtr;
            mOwnsNativeParcelObject = false;
        } else {
            mNativePtr = nativeCreate();
            mOwnsNativeParcelObject = true;
        }
    }

因为nativePtr等于0,所以会调用nativeCreate来创建Native层的Parcel对象,代码在android_os_Parcel.cpp中:

static jint android_os_Parcel_create(JNIEnv* env, jclass clazz)
{
    Parcel* parcel = new Parcel();
    return reinterpret_cast<jint>(parcel);
}

在mNativePtr就保存中Native层的Parcel对象的地址,当使用完调用recycle时,先调用JNI层的freeBuffer()来释放Native层的Parcel对象所申请的存储数据的内存空间,然后将它自己放到Parcel pool中,这样下一次再用Parcel时,就不要再次分配了。来看一下freeBuffer()的实现:

static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jint nativePtr)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        parcel->freeData();
    }
}

void Parcel::freeData()
{
    freeDataNoInit();
    initState();
}

我们在前面分析过freeDataNoInit的方法,它通过向binder驱动发送BC_FREE_BUFFER命令来释放binder驱动申请的binder_buffer。initState用于恢复初始状态。回到ServiceManagerProxy的addService的方法,与Native层注册Service一样,这里首先写入Strict mode和"android.os.IServiceManager",然后再写入要注册的Service的名字"wifi",再写入Service本身,这里我们主要分析下writeInterfaceToken和writeStrongBinder两个方法:

static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jint nativePtr,
                                                  jstring name)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        const jchar* str = env->GetStringCritical(name, 0);
        if (str != NULL) {
            parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
            env->ReleaseStringCritical(name, str);
        }
    }
}

nativePtr就是前面在调用android_os_Parcel_create时申请的Native层Parcel对象的地址指针,通过reinterpret_cast将它转换为Parcel对象。然后就调用Native层的Parcel对象的writeInterfaceToken方法,这里比较简单。在来看一下writeStrongBinder方法:

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jint 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);
        }
    }
}

前面有说过Binder的构造函数会调用JNI的android_os_Binder_init方法,这里先来分析一下。然后再来分析ibinderForJavaObject方法。

static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    if (jbh == NULL) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return;
    }
    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
    jbh->incStrong((void*)android_os_Binder_init);
    env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
}

这里构造一个JavaBBinderHolder对象并把它的地址保存在Binder类的mObject上。接着来看ibinderForJavaObject方法:

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

    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetIntField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }

    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            env->GetIntField(obj, gBinderProxyOffsets.mObject);
    }

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

因为WifiService是继承于Binder,首先从WifiSerivce对象的mObject上取出JavaBBinderHolder对象,然后调用它的get方法:

class JavaBBinderHolder : public RefBase
{
public:
    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=%d\n",
                 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
        }

        return b;
    }

    sp<JavaBBinder> getExisting()
    {
        AutoMutex _l(mLock);
        return mBinder.promote();
    }

private:
    Mutex           mLock;
    wp<JavaBBinder> mBinder;
};

在第一次进入到get方法是mBinder并没有赋值,所以它的promote方法返回NULL,所以这里先创建一个JavaBBinder对象,并赋值给mBinder,然后返回。这里的JavaBBinder是继承于BBinder,所以它是一个Bn端,并实现了onTransact方法。至于如何调用这里的onTransact方法,我们下一章再来分析。这里只需要记住在Binder.java中的mObject变量保存了JavaBBinderHolder对象,在JavaBBinderHolder对象中的mBinder中保存了一个JavaBBinder对象,在JavaBBinder保存了真正的WifiService对象。回到android_os_Parcel_writeStrongBinder函数中,接着调用Native层Parcel的writeStrongBinder方法将上面的JavaBBinder写入。再回到ServiceManagerProxy的addService方法中,接着调用mRemote.transact方法,这里的mRemote就是BinderProxy对象,所以来看BinderProxy的transact,它的实现也在android_util_Binder.cpp中。

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    if (dataObj == NULL) {

    }

    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL) {
        return JNI_FALSE;
    }
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }

    IBinder* target = (IBinder*)
        env->GetIntField(obj, gBinderProxyOffsets.mObject);
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }

    ALOGV("Java code calling transact on %p in Java object %p with code %d\n",
            target, obj, code);

    status_t err = target->transact(code, *data, reply, flags);

    if (err == NO_ERROR) {
        return JNI_TRUE;
    } else if (err == UNKNOWN_TRANSACTION) {
        return JNI_FALSE;
    }

    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
    return JNI_FALSE;
}

首先取出data和reply两个Parcel对象,然后从BinderProxy的mObject处取出BpBinder(0),然后调用它的transact方法,到这里就全部回到Native层注册Servcie的流程了。