天天看点

Binder 通信笔记(Java)概述Service注册获取service_manager代理Service的初始化addServiceBinder驱动调用Service参考资料

  • 概述
  • Service注册
  • 获取service_manager代理
  • Service的初始化
  • addService
  • Binder驱动调用Service
  • 参考资料

概述

在上一节Binder 通信笔记(native)中,分析了在c++层service和client是怎样与binder驱动通信的。在Android中,绝大部分的应用和很多关键的系统Service是用Java来完成的。这一节,我们分析一下Java层程序是如何使用binder驱动进行通信的。其实Java层的binder通信是基于native的,它只是把binder的“网络层”(BpBinder和BBinder)做了一下封装,通过JNI将业务发送给了上一层。先看以下结构图

Binder 通信笔记(Java)概述Service注册获取service_manager代理Service的初始化addServiceBinder驱动调用Service参考资料

可以看到native层的类关系图和上一节下半部分完全相同,java层多了BinderProxy.class和Binder.class将native层的数据传送到上层。这一节我们只分析上半部分代码,下半部分的代码请查看上一节Binder 通信笔记(native)。

Service注册

这一节以ActivityManagerService为例,分析以下Java层Service注册到serviceManager的过程。ActivityManagerService是在SystemServer进程里面注册的,本节以分析binder为主,SystemServer的启动过程这里就不说了,网上有很多资料。大概流程是

SystemServer:main()
    ->run()
        ->startBootstrapServices()
            ->mActivityManagerService.setSystemProcess();
                ->ServiceManager.addService("activity", this, true);
           

下面看一下ServiceManager.addService的实现。

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

获取service_manager代理

在Java层有一个ServiceManager.class作为service_manager的代理,它是如何实现的呢,我们继续跟代码,看一下

getIServiceManager()

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

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

ServiceManager是一个单例实现,第一次初始化执行了

ServiceManagerNative.asInterface(BinderInternal.getContextObject())

。先看一下括号里吗的参数。

BinderInternal.getContextObject()

是一个native函数。它的实现在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), 这个0就代表着远程为service_manager。继续看一下javaObjectForIBinder();

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

    //1
    if (val->checkSubclass(&gBinderOffsets)) {
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }

    AutoMutex _l(mProxyLock);

      jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    // 2
    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);
    }

    //3
    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.
        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;
}
           

参数val为BpBinder(0),checkSubclass()函数使用IBinder里面的实现,直接返回false,所以1里的if为false。2里面是看一下是不是已经初始化过,直接进行返回,第一次引用是肯定为空,我们直接看3下面的代码。看代码之前先补充一下gBinderProxyOffsets。它是一个结构体,在jni进行init时

int_register_android_os_BinderProxy()

进行的初始化。看一下这个结构体,注释里是它值

static struct binderproxy_offsets_t
{
    // Class state.
    jclass mClass;               //android.os.BinderProxy
    jmethodID mConstructor;      //android.os.BinderProxy.<init>()
    jmethodID mSendDeathNotice;  //android.os.BinderProxy.sendDeathNotice()

    // Object state.
    jfieldID mObject;  //android.os.BinderProxy.mObject
    jfieldID mSelf;    //android.os.BinderProxy.mSelf
    jfieldID mOrgue;   //android.os.BinderProxy.mOrgue

} gBinderProxyOffsets;
           

再分析javaObjectForIBinder第3段代码可以看出来是首先创建了一个BinderProxy的Java对象,并且把它的成员变量mObject指向BpBinder。同时BpBinder的持有BinderProxy,方便第二次调用时直接返回。

所以

BinderInternal.getContextObject()

返回的是BinderProxy对象。下面再看一下

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

直接new一个ServiceManagerProxy返回。我们看一下他的类关系图

Binder 通信笔记(Java)概述Service注册获取service_manager代理Service的初始化addServiceBinder驱动调用Service参考资料

替换一下,

getIServiceManager()

就是

new ServiceManagerProxy(new BinderProxy())

。这样我们其实就是调用的ServiceManagerProxy的addService()函数。

Service的初始化

在分析addService()之前,我们需要先看一下ActivityManagerService的初始化过程,先看以下它的类关系图

Binder 通信笔记(Java)概述Service注册获取service_manager代理Service的初始化addServiceBinder驱动调用Service参考资料

ActivityManagerService的继承关系在上图中一目了然 。我们重点关注一下Binder的构造函数,在这里做了一些重要的初始化工作,在addService的时候会用到。Binder的初始化就是调用了一个init()函数,这个init()函数是一个 native函数,它的实现在android_util_Binder.cpp里面。

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->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}
           

创建了一个JavaBBinderHolder对象,并把指针赋给Binder.mObject。gBinderOffsets和前面的gBinderProxyOffsets类似,也是在程序启动时初始化的,他的结构体代码如下

static struct bindernative_offsets_t
{
    // Class state.
    jclass mClass;                //android.os.Binder
    jmethodID mExecTransact;      //android.os.Binder.execTransact();

    // Object state.
    jfieldID mObject;             //android.os.Binder.mObject

} gBinderOffsets;
           

分析完Service的初始化之后,我们再看一下Service是怎样通过ServiceManagerProxy注册到service_manager里面的。

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

先把service写入到序列化类Parcel里面。然后调用mRemote.transact(),将序列化的数据发送出去。这里的mRemote就是我们前面初始化ServiceManagerProxy传入的BinderProxy。下面看一下Parcel.writeStrongBinder()

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

nativeWriteStrongBinder是一个jni的调用,它的实现在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);
        }
    }
}
           

parcel->writeStrongBinder()

在上一节已经分析过,如果是一个BpBinder它会将handle的值存入parcel中,如果是BBinder它会将BBinder 的this指针存储到 parcel中。这里我们是addService操作,所以我们可以大胆猜测括号里是一个BBinder的子类。下面我们看一下ibinderForJavaObject(env, object)是如何实现将Java的Servie和BBinder绑定的。

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

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

    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {//BinderProxy.class
        return (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }

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

这里的obj是ActivityManagerService,它是Binder的子类。所以执行第二个if语句。还记得我们前面在讲Binder的构造函数时,在init里面我们在native层分配了一个JavaBBinderHolder类,并将它的指针存在mObject成员变量中。现在我们把它取出来然后调用他的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=%" PRId32 "\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为空,于是创建了一个JavaBBinder,并把obj传了进去。然后把JavaBBinder赋值给mBinder。接着看看JavaBBinder

class JavaBBinder : public BBinder
{
public:
    JavaBBinder(JNIEnv* env, jobject object)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
    {
        ALOGV("Creating JavaBBinder %p\n", this);
        android_atomic_inc(&gNumLocalRefs);
        incRefsCreated(env);
    }

    bool    checkSubclass(const void* subclassID) const
    {
        return subclassID == &gBinderOffsets;
    }

    jobject object() const
    {
        return mObject;
    }

protected:
    virtual ~JavaBBinder()
    {
        ALOGV("Destroying JavaBBinder %p\n", this);
        android_atomic_dec(&gNumLocalRefs);
        JNIEnv* env = javavm_to_jnienv(mVM);
        env->DeleteGlobalRef(mObject);
    }

    virtual status_t onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = )
    {
        ...
    }

    virtual status_t dump(int fd, const Vector<String16>& args)
    {
        return ;
    }

private:
    JavaVM* const   mVM;
    jobject const   mObject;
};
           

JavaBBinder会把传进来的service引用赋值给自己的mObject。可以看出Binder.class,JavaBBinderHolder,JavaBBinder这三者是一个循环持有的过程,他们的关系图为

Binder 通信笔记(Java)概述Service注册获取service_manager代理Service的初始化addServiceBinder驱动调用Service参考资料

这样Java层和c++层都持有了对方的引用。

同时JavaBBinder还是BBinder的子类。也就是说,ibinderForJavaObject返回了JavaBBinder也就是一个BBinder。下面我们看一下BinderProxy.transact()函数。

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

transactNative()是一个jni实现,它的源码在android_os_Parcel.cpp

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

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

    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);//3
    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 %" PRId32 "\n",
            target, obj, code);


    //printf("Transact from Java code to %p sending: ", target); data->print();
    status_t err = target->transact(code, *data, reply, flags);//4


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

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

在1,2里面分别把Java序列化的data和reply转变为一个c++的Parcle变量。3中取出了mObject值,在前面获得server_manager代理的时候我们把他初始化为一个BpBinder(0)。在4里面调用BpBinder->transact()函数。下面就进入了C++层和binder通信的过程,和上一篇博客分析的一样,会调用到IPCThreadState和binder驱动进行读写。到这里我们就已经把我们的ActivityManagerService注册到Binder驱动和 activity_manager里面 。

Binder驱动调用Service

上一节我们分析了Java中的Service如何注册到binder里面的。那么,binder又是如何调用到Service的业务实现的呢。在上一篇博客Binder通信笔记(native)篇中,我们看到在IPCProcessState读取到binder数据之后,会通过我们注册到binder驱动里面BBinder指针,调用它的transact()函数。在Java Serivce注册的时候,我们注册的是JavaBBinder,它是BBinder的子类。JavaBBinder并没有重写transact()函数,所以回复用BBinder中的实现,调用onTransact()函数。JavaBBinder重写了onTransact()的实现,我们看一下源码

virtual status_t onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = )
    {
        JNIEnv* env = javavm_to_jnienv(mVM);

        ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);

        IPCThreadState* thread_state = IPCThreadState::self();
        const int32_t strict_policy_before = thread_state->getStrictModePolicy();

        //printf("Transact from %p to Java code sending: ", this);
        //data.print();
        //printf("\n");
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
        jthrowable excep = env->ExceptionOccurred();

        if (excep) {
            report_exception(env, excep,
                "*** Uncaught remote exception!  "
                "(Exceptions are not yet supported across processes.)");
            res = JNI_FALSE;

            /* clean up JNI local ref -- we don't return to Java code */
            env->DeleteLocalRef(excep);
        }

        // Check if the strict mode state changed while processing the
        // call.  The Binder state will be restored by the underlying
        // Binder system in IPCThreadState, however we need to take care
        // of the parallel Java state as well.
        if (thread_state->getStrictModePolicy() != strict_policy_before) {
            set_dalvik_blockguard_policy(env, strict_policy_before);
        }

        jthrowable excep2 = env->ExceptionOccurred();
        if (excep2) {
            report_exception(env, excep2,
                "*** Uncaught exception in onBinderStrictModePolicyChange");
            /* clean up JNI local ref -- we don't return to Java code */
            env->DeleteLocalRef(excep2);
        }

        // Need to always call through the native implementation of
        // SYSPROPS_TRANSACTION.
        if (code == SYSPROPS_TRANSACTION) {
            BBinder::onTransact(code, data, reply, flags);
        }

        //aout << "onTransact to Java code; result=" << res << endl
        //    << "Transact from " << this << " to Java code returning "
        //    << reply << ": " << *reply << endl;
        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
    }
           

第15行,调用了mObject的gBinderOffsets.mExecTransact函数,通过前面的分析知道,此处的mObject是一个Binder类的引用,gBinderOffsets.mExecTransact是Binder类的execTransact()方法。所以,业务处理分发给了Java层的Binder类的execTransact()。

// Entry point from android_util_Binder.cpp's onTransact
private boolean execTransact(int code, long dataObj, long replyObj,
            int flags) {
        Parcel data = Parcel.obtain(dataObj);
        Parcel reply = Parcel.obtain(replyObj);
        // theoretically, we should call transact, which will call onTransact,
        // but all that does is rewind it, and we just got these from an IPC,
        // so we'll just call it directly.
        boolean res;
        // Log any exceptions as warnings, don't silently suppress them.
        // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
        try {
            res = onTransact(code, data, reply, flags);
        } catch (RemoteException e) {
            if ((flags & FLAG_ONEWAY) != ) {
                Log.w(TAG, "Binder call failed.", e);
            } else {
                reply.setDataPosition();
                reply.writeException(e);
            }
            res = true;
        } catch (RuntimeException e) {
            if ((flags & FLAG_ONEWAY) != ) {
                Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
            } else {
                reply.setDataPosition();
                reply.writeException(e);
            }
            res = true;
        } catch (OutOfMemoryError e) {
            // Unconditionally log this, since this is generally unrecoverable.
            Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);
            RuntimeException re = new RuntimeException("Out of memory", e);
            reply.setDataPosition();
            reply.writeException(re);
            res = true;
        }
        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
        reply.recycle();
        data.recycle();

        // Just in case -- we are done with the IPC, so there should be no more strict
        // mode violations that have gathered for this thread.  Either they have been
        // parceled and are now in transport off to the caller, or we are returning back
        // to the main transaction loop to wait for another incoming transaction.  Either
        // way, strict mode begone!
        StrictMode.clearGatheredViolations();

        return res;
    }
           

这里调用了onTransact(code, data, reply, flags),onTransact()在ActivityManagerService里面被继承了,真正的业务处理放在了这里 ,这样我们的Service函数就会被真正的执行,并且把执行后的结构存储在reply里面。

到这里我们就分析完了Java层和Binder驱动通信源码。

参考资料

http://blog.csdn.net/universus/article/details/6211589

http://blog.csdn.net/luoshengyang/article/details/6618363

http://blog.csdn.net/innost/article/details/47208049