Binder Framework通信我之见解

来源:互联网 发布:蚕丝被淘宝买什么牌子 编辑:程序博客网 时间:2024/05/29 17:18

1.Binder Native 层家族

Binder类在Native层有两个重要的子类BBinder 和BpBinder,其中BBinder代表通信的服务端,BpBinder代表通信的客户端。

这幅类关系图中BnInterface继承了BBinder对象表示服务端的binder,BpInterfce 继承BpRefBase 对象,通过mRemote 持有BpBinder对象表示客户端的binder对象,INTERFACE表示具体的业务类接口,通常该业务类接口还需实现IInterface中的函数,BnInterface<INTERFACE>这个模板类,实际是表示了继承BBinder和INTERFACE。类的详细定义如下:

template<typename INTERFACE>

class BnInterface : public INTERFACE, public BBinder

{

public:

    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);

    virtual const String16&     getInterfaceDescriptor() const;

protected:

    virtual IBinder*            onAsBinder();

};

BpInterface<INTERFACE>也是模板类,实际与BnInterface<INTERFACE>定义类似,该类表示继承BpRefBase和INTERFACE两个类,详细定义如下:

template<typename INTERFACE>

class BpInterface : public INTERFACE, public BpRefBase

{

public:

    BpInterface(const sp<IBinder>& remote);

protected:

    virtual IBinder*            onAsBinder();

};

如下将介绍Native的相关服务对binder 通信进行分析。

1.1 IServiceManager类图分析

Native层很多服务也运用了Binder通信,如下通过ServiceManager在Native的通信过程,去了解Binder的通信原理。

在讲解Binder通信前,首先理解IServiceManager家族的类关系图,如下:

IServiceManager相当于Binder关系图中提到的INTERFACE模板,实现了IInterface中定义的接口函数。这里BnInterface<IServiceManager>除了继承了BBinder外,相当于还实现了IServiceManager接口,同理BpInterface<IServiceManager>除了继承BpRefBase外,也还实现了IServiceManager接口。BnServiceManager就是继承BnInterface<IServiceManager>,这样即具有了服务端通信的BBinder对象,又实现了IServiceManager的接口函数。BpServiceManager则是通过BpRefBase持有的mRemote(BpBinder类型)对象与服务端通信,并通过实现IServiceManager接口,完成通信的业务。

1.2 IServiceManager客户端通信代理获取

Native层的IServiceManager 的客户端对象是如何获取的?在IServiceManager中存在defaultServiceManager接口,让native程序获取IServiceManager客户端的业务对象,该对象是单实例的,实际这个对象是BpServiceManager类型的。

sp<IServiceManager> defaultServiceManager()

{

    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

    {

        AutoMutex _l(gDefaultServiceManagerLock);

        while (gDefaultServiceManager == NULL) {

            gDefaultServiceManager = interface_cast<IServiceManager>(

                ProcessState::self()->getContextObject(NULL));

            if (gDefaultServiceManager == NULL)

                sleep(1);

        }

    }

    return gDefaultServiceManager;

}

实例化该对象时,程序首先调用了ProcessState::self()->getContextObject(NULL)得到一个BpBinder对象,这里不详细说明,可跟踪代码了解,另外interface_cast实际上是IInterface类中定义的模板方法,而IServiceManager是继承了IInterface类的,模板方法的定义如下:

template<typename INTERFACE>

inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)

{

    return INTERFACE::asInterface(obj);

}

INTERFACE是IServiceManager,所以该方法的实际调用是IServiceManager::asInterface(obj);

asInterface是在IInterface定义的模板: DECLARE_META_INTERFACE(INTERFACE),由于继承关系(IServiceManager继承了IInterface)相当于IServiceManager定义了DECLARE_META_INTERFACE(ServiceManager)

#define DECLARE_META_INTERFACE(INTERFACE)                            \

    static const android::String16 descriptor;                          \

    static android::sp<I##INTERFACE> asInterface(                       \

            const android::sp<android::IBinder>& obj);                  \

    virtual const android::String16& getInterfaceDescriptor() const;    \

    I##INTERFACE();                                                     \

    virtual ~I##INTERFACE();                                            \

IMPLEMENT_META_INTERFACE也是在IInterface定义的模板,它表示DECLARE_META_INTERFACE(INTERFACE)的实现,IServiceManager继承的实现如下:

IMPLEMENT_META_INTERFACE(ServiceManager,"android.os.IServiceManager");

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \

    const android::String16 I##INTERFACE::descriptor(NAME);             \

    const android::String16&                                            \

            I##INTERFACE::getInterfaceDescriptor() const {              \

        return I##INTERFACE::descriptor;                                \

    }                                                                   \

    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \

            const android::sp<android::IBinder>& obj)                   \

    {                                                                   \

        android::sp<I##INTERFACE> intr;                                 \

        if (obj != NULL) {                                              \

            intr = static_cast<I##INTERFACE*>(                          \

                obj->queryLocalInterface(                               \

                        I##INTERFACE::descriptor).get());               \

            if (intr == NULL) {                                         \

                intr = new Bp##INTERFACE(obj);                          \

            }                                                           \

        }                                                               \

        return intr;                                                    \

    }                                                                   \

    I##INTERFACE::I##INTERFACE() { }                                    \

    I##INTERFACE::~I##INTERFACE() { }                                   \

#define CHECK_INTERFACE(interface, data, reply)                         \

    if (!data.checkInterface(this)) { return PERMISSION_DENIED; }       \

通过模板定义的接口实现,最终返回客户端的业务对象Bp##INTERFACE(obj)即BpServiceManager对象。

1.3 IServiceManager客户端通信过程分析

根据获取到的业务对象,由于业务对象已经具备binder通信的客户端,所以可通过该业务对象进行添加新服务、查询服务等操作。这里介绍addService的实现,该过程时序图所示。   defaultServiceManager()->addService(           String16("media.player"), new MediaPlayerService());上面的defaultServiceManager()表示BpServiceManager。

IPCThreadState::transact函数中传入的flags需要做关注,这里它加入了标志TF_ACCEPT_FDS,并判断是否有TF_ONE_WAY,因为传入的值默认为0,所以这里不会携带TF_ONE_WAY.这两个特殊的宏实际定义在了./include/uapi/linux/android/binder.h。

enum transaction_flags {

//异步通信或者没返回值则使用该标志

       TF_ONE_WAY      = 0x01,   /*this is a one-way call: async, no return */

       //允许通过binder文件描述符返回,这里似乎都要加入该标志

       TF_ACCEPT_FDS = 0x10,   /*allow replies with file descriptors */

};

所以这个IPCThreadState::transact是同步的函数,即必须要服务端返回数据,才算完成通信。

status_t IPCThreadState::transact(int32_t handle,

                                  uint32_t code, const Parcel& data,

                                  Parcel* reply, uint32_t flags)

{……….

    flags |= TF_ACCEPT_FDS;

    if (err == NO_ERROR) {

        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),

            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");

        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);

    }

…………

}

BpServiceManager的业务函数addService的整体过程比较简单,就是将需要发送的数据打包成Parcel对象后,由BpBinder对象传递给IPCThreadState(一个与线程相关的状态对象),IPCThreadState将检查数据的完整正确性,并将数据转化成binder_transaction_data类型的数据,最终将数据写道mOut(相当于该线程对象与binder的通信缓存)变量中,在上层这就完成了一次数据的传输,当然之后的事情需要驱动完成。

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,

    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)

{

    binder_transaction_data tr;

    tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */

    ………….

    const status_t err = data.errorCheck();

    if (err == NO_ERROR) {

        tr.data_size = data.ipcDataSize();

        tr.data.ptr.buffer = data.ipcData();

        tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);

        tr.data.ptr.offsets = data.ipcObjects();

    …………….

    mOut.writeInt32(cmd);//先写命令BC_TRANSACTION

    mOut.write(&tr, sizeof(tr));//后写数据,数据类型binder_transaction_data

   

    return NO_ERROR;

}

发送完数据后,需要等待服务端的返回信息,这个过程由IPCThreadState的waitForResponse函数完成。waitForResponse通过talkWithDriver与设备通信,获取信息返回的状态,并根据信息的类型做出不同的处理。这样就完成了一次Binder通信处理。

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)

{

    int32_t cmd;

    int32_t err;

    while (1) {

        if ((err=talkWithDriver()) < NO_ERROR) break;//1.与驱动通信

        err = mIn.errorCheck();

        if (err < NO_ERROR) break;

        if (mIn.dataAvail() == 0) continue;

       

        cmd = mIn.readInt32();//驱动会将服务端回复的信息,写到mIn中,回复的消息类型需要根据驱动的实现确定,这里不深究。

         //…..….

        switch (cmd) {//第一次读取的是信息的类型,客户端根据不同的信息做不同的处理

        case BR_TRANSACTION_COMPLETE:

            if (!reply && !acquireResult) goto finish;

            break;

       

        case BR_DEAD_REPLY:

            err = DEAD_OBJECT;

            goto finish;//……….  

        default://如果上面没有找到信息类型,则交由executeCommand函数处理

            err = executeCommand(cmd);

            if (err != NO_ERROR) goto finish;

            break;

        }

    }

//……………..

    return err;

}

1.4 IMediaPlayerService服务端接收信息处理

    virtual sp<IMediaRecorder> createMediaRecorder()

    {

        Parcel data, reply;

        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());

        remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);

        return interface_cast<IMediaRecorder>(reply.readStrongBinder());

    }

由于IServiceManager通信并不涉及BnxxxService封装的通信,而是直接在服务端读写Binder设备,进行消息处理的。所以这里将分析BnMediaPlayService的通信原理,进一步了解Binder通信在服务封装的机制。假设此时服务端MediaPlayerService启动,那必然会开启线程通过talkWithDriver()函数与Binder设备通信。如果此时收到客户端的请求,比如客户端通过BpMediaPlayerService调用createMediaRecorder业务函数,经过binder设备通信,服务端进行调用talkWithDriver获取到信息的类型,IPCThreadState::waitForResponse就会根据不同的返回类型,做不同的处理。而这里最终是在IPCThreadState的executeCommand函数中做处理的:

case BR_TRANSACTION:{

            binder_transaction_data tr;

            result = mIn.read(&tr, sizeof(tr));

………….

            if (tr.target.ptr) {//这里调用BBinder 的transact 函数,最终会调用到子类的onTransact 函数,而实现该方法的子类为BnMediaPlayerService

                sp<BBinder> b((BBinder*)tr.cookie);

                error = b->transact(tr.code, buffer, &reply, tr.flags);

            } else {

                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);

            }

            mCallingPid = origPid;

            mCallingUid = origUid;

            mStrictModePolicy = origStrictModePolicy;

            mLastTransactionBinderFlags = origTransactionBinderFlags;           

        }

        break;

   

看一下BBinder::transact函数,最终会调用onTransact函数,BnMediaPlayerService则重新实现了该函数

status_t BBinder::transact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

……….

    switch (code) {

        case PING_TRANSACTION:

            reply->writeInt32(pingBinder());

            break;

        default:

            err = onTransact(code, data, reply, flags);

            break;

    }

……….  

}

 

status_t BnMediaPlayerService::onTransact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

…………

    switch (code) {     

  case CREATE_MEDIA_RECORDER: {

            CHECK_INTERFACE(IMediaPlayerService, data, reply);

//这里就会调用服务端的createMediaRecorder函数,这个函数由BnMediaPlayerService子类MediaPlayerService实现

            sp<IMediaRecorder> recorder = createMediaRecorder();

            reply->writeStrongBinder(recorder->asBinder());

            return NO_ERROR;

…………

这样就完成从客户端到服务端的通信。

2.Binder Java 层家族

Java层Binder系统是Native层Binder系统的一个镜像,其最终也是借助Native层Binder系统完成通信的。Java层的Binder系统通过JNI的调用,在Java世界初创的时期完成与Native层映射。

Java Binder通过上面jni的调用完成了几个重要全局静态变量的初始化,分别是gBinderOffsets、gBinderInternalOffsets、gBinderProxyOffsets.实际这些变量就是提前获取了一些JNI层的使用信息,如类的成员变量和函数等。如下是这些成员结构体的类解析:

int_register_android_os_Binder代码的作用是获取的java层相关信息保存在结构体bindernative_offsets_t类型的变量中mClass:表示android/os/Binder这个类的实例mExecTransact:表示java层Binder的execTransact方法mObject:java层的成员变量,用于保存native层Binder的相关信息(JavaBBinderHolder)

int_register_android_os_BinderInternal则是获取java层的相关信息保存到结构体binderinternal_offsets_t中mClass:表示com/android/internal/os/BinderInternal这个类的实例mForceGc:表示java层BinderInternal的forceBinderGc方法

int_register_android_os_BinderProxy中除了获取BinderProxy的相关信息,还获取了其他调用类的信息,这里只解释BinderProxy的信息mClass:表示android/os/BinderProxy这个类的实例mConstructor : 表示BinderProxy的构造方法mSendDeathNotice:表示BinderProxy的sendDeathNotice静态方法mObject:表示BinderProxy的成员变量mObject,用于保存native BpBinder对象mSelf:表示java/lang/ref/WeakReference对象,表示对象的引用信息。mOrgue:表示java层的成员变量mOrgu

2.1 ServiceManager 类图分析

上面是ServiceManager家族的关系图ServiceManager实际是个封装类,其客户端的通信最终实现是通过ServiceManagerNative. asInterface接口返回的类ServiceManagerProxy实现,ServiceManagerNative实际是服务端通信的空实现,因为servicemanager的服务端并没有用Binder封装,而是直接通过操作Binder设备进行通信。

2.2 ServiceManager 客户端通信实现

之前提到ServiceManagerProxy作为客户端通信的代码,需要从ServiceManagerNative. asInterface接口中返回。

private static IServiceManager getIServiceManager() {

……..     sServiceManager=ServiceManagerNative.asInterface(BinderInternal.getContextObject());

 return sServiceManager;

}

 

用户如果要添加java层服务,则需ServiceManager的addService 接口完成,其实际首先调用了ServiceManagerNative.asInterface(如下代码)接口获取servicemanager在java层的代理ServiceManagerProxy对象,然后调用了ServiceManagerProxy的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);

        }

    }

要看如何添加服务的,需要先了解ServiceManagerProxy是如何初始化的,它是在ServiceManagerNative.asInterface(BinderInternal.getContextObject());完成的初始化。

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对象。javaObjectForIBinder这个函数是通过Native对象创建一个Java对象。

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)

{//val实际是一个BpBinder对象

//……………

//通过调用java层的BinderProxy的构造方法,新建一个BinderProxy对象。

   object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);

   if (object != NULL) {//完成native与java层的映射关系。

        LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);

        // The proxy holds a reference to the native object.

//下面就是将BpBinder保存到java层的BinderProxy的mObject中

        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;//将创建的对象返回

}

即javaObjectForIBinder返回的是一个BinderProxy 对象,所以得到的是ServiceManagerNative.asInterface(BinderProxy bp),即ServiceManagerProxy构造函数传入的是BinderProxy,保存在mRemote对象中。这就完成了ServiceManagerProxy的初始化。

当调用addService接口时,即利用了mRemote将数据往外传递

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

    }

mRemote为BinderProxy,可看到transact是调用transactNative jni函数完成通信。

    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_BinderProxy_transact,实现如下:

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,

        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException

{

    //………..

    //这里可以看到,将之前保存在java层的Native BpBinder获取到。

    IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);

    //……………..

    //最终调用native层的对象完成通信

    //printf("Transact from Java code to %p sending: ", target); data->print();

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

    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();

    //……….

    return JNI_FALSE;

}

可得出的结论,Java层的Binder架构最终还是要借助Natvie的Binder架构进行通信。

2.3 ActivityManagerNative服务端接收信息处理

ActivityManagerNative代码服务端的通信实现,ActivityManagerProxy则代码客户端的通信实现。ActivityManagerService则表示服务端的业务的实现。

这分析通信之前,需要了解java层的Binder对象是如何与Natvie层的BBinder进行关联的。

在新建一个ActivityManagerService服务时,即调用newActivityManagerService(context);时,由于继承关系,所以会调用Binder对象的构造方法。

    /**

     * Default constructor initializes the object.

     */

    public Binder() {

        init();

……….

    }

Binder的构造方法存在一个jni函数,该方法有init,它的实现如下:

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

//这里将jbh保存到Binder的mObject对象中。

    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);

}

通过该构造函数调用后,Binder的成员变量mObject指向了 JavaBBinderHolder对象,对JavaBBinderHolder进行剖析,可以看出java层的Binder对象如何与Native层的BBinder对象关联起来的:

JavaBBinderHolder提供了一个接口sp<JavaBBinder>get(JNIEnv* env, jobject obj)可返回JavaBBinder对象,进而得到BBinder对象。如果此时客户端通信发送信息到ActivityManagerNative代表的服务端,则服务端应该怎么处理呢?在android_util_Binder.cpp中会调用如下函数处理。

    virtual status_t onTransact(

        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)

    {

//…………………这里的mObject表示ActivityManagerService

        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,

            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

        jthrowable excep = env->ExceptionOccurred();

//………………….

    }

会调用execTransact函数,该函数在Binder中实现,最终该函数是调用子类的onTransact函数。onTransact由ActivityManagerNative实现,而onTransact没一种情况的处理即业务函数,则由ActivityManagerService实现。通过这样就可以完成业务函数的处理了。

3.Binder与Aidl的实现

3.1 IPackageManager.aidl的实现关系图

IPackageManager.aidl在经过aidl的工具处理后,会生成如下的类。这些类最终都会与Binder系统关联上,可以这样说aidl是将实现了业务通信架构。IPackageManager.Stub代表了服务端通信端的实现,IPackageManager.Stub.Proxy则为客户端的通信实现。可进一步看到android对这个通信系统的实现是PackageManagerService通过继承IPackageManager.Stub完成业务函数的实现。而ApplicationPackageManager通过持有IPackageManager.Stub.Proxy对象封装客户端通信的接口。

所以aidl实际就是将业务函数与Binder系统完成关联。
0 0
原创粉丝点击