Binder 通信笔记(Java)

来源:互联网 发布:社会静力学知乎 编辑:程序博客网 时间:2024/06/05 23:14

  • 概述
  • 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将业务发送给了上一层。先看以下结构图
这里写图片描述

可以看到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返回。我们看一下他的类关系图
这里写图片描述

替换一下,getIServiceManager() 就是 new ServiceManagerProxy(new BinderProxy()) 。这样我们其实就是调用的ServiceManagerProxy的addService()函数。

Service的初始化

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

这里写图片描述

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 = 0)    {        ...    }    virtual status_t dump(int fd, const Vector<String16>& args)    {        return 0;    }private:    JavaVM* const   mVM;    jobject const   mObject;};

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

这样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 = 0)    {        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 onTransactprivate 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) != 0) {                Log.w(TAG, "Binder call failed.", e);            } else {                reply.setDataPosition(0);                reply.writeException(e);            }            res = true;        } catch (RuntimeException e) {            if ((flags & FLAG_ONEWAY) != 0) {                Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);            } else {                reply.setDataPosition(0);                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(0);            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

0 0