Binder通信相关的类简要分析

一、BpBinder

这个类通常作为IPC通信的Client端,或者说Remote端,提供实际的IPC基础通信服务。在代码中通常不直接使用到该类,一般以成员变量的形式,包含于BpRefBase类中,通过remote()方法引用该成员变量。继承关系如下:

 

BpXXX --> BpInterface<IXXX> --> BpRefBase

 

在BpXXX方法中,就可以直接通过remote()方法引用到BpBinder实例,继而利用其提供的IPC通信功能,通过Binder协议与另一端进行通信。

 

BpBinder类的定义说明

 

成员变量分析:

const   int32_t             mHandle;//handle for remote obj

            void                reportOneDeath(const Obituary& obit);
            bool                isDescriptorCached() const;

    mutable Mutex               mLock;
            volatile int32_t    mAlive;
            volatile int32_t    mObitsSent; //we have already send Obit? can notify is object is already dead
            Vector<Obituary>*   mObituaries;//dead notification listerners
            ObjectManager       mObjects;
            Parcel*             mConstantData;
    mutable String16            mDescriptorCache;


mHandle: 这是一个重要的成员变量,代表Binder驱动为一个远程对象分配的一个句柄,在Binder驱动中,通过该句柄号,找到对应的Binder引用结点,通过Binder引用结点,找到其引用的位于不同进程中的一个Binder结点,从而将利用该Binder结点将通信数据路由到通信的另一端所在的进程。

mLock:保护BpBinder对象的一些方法的访问,从而保证任何时刻不会同时执行两个或以上方法。

mAlive:Binder IPC通信是否处于活跃状态。

mObjects:对象管理,主要是对Java Binder对象的管理。

mConstantData:未使用

mDescriptorCache:保存接口描述信息。

 

 

主要方法分析:

  virtual status_t    transact(   uint32_t code,

                                    const Parcel&data,

                                    Parcel*reply,

                                    uint32_tflags = 0);

  该方法是Binder IPC通信的入口,其实质上是调用IPCThreadState类的transact方法。

 

如下两个接口则是提供监听远程对象死亡通知的接口。

   virtual status_t   linkToDeath(const sp<DeathRecipient>& recipient,

                                    void*cookie = NULL,

                                    uint32_tflags = 0);

   virtual status_t   unlinkToDeath(  constwp<DeathRecipient>& recipient,

                                        void*cookie = NULL,

                                       uint32_t flags = 0,

                                       wp<DeathRecipient>* outRecipient = NULL);

 

BpBinder对象作为远程对象的代理,它会跟踪远程对象的状态(实质上是在驱动中,跟踪Binder通信结点,结点死亡的信息也是通过驱动层向用户空间发送的),一旦接收到死亡通知,则会调用如下接口通知所有监听者:

void  sendObituary();

其会调用如下方法调用所有监听者提供的回调函数:

void reportOneDeath(const Obituary& obit);


二、BBinder

 

BBinder类作为Binder IPC通信的Server端或Local端,处理来自Client端或Remote端的服务请求。它的主要方法就是处理请求:

status_t BBinder::transact(

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

 

在IPCThreadState中,是通过如下方式调用到上述的接口的:


IPCThreadState(979):         
case BR_TRANSACTION:
           …   
if (tr.target.ptr) {//local 
                sp<BBinder> b((BBinder*)tr.cookie);
                const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
                if (error < NO_ERROR) reply.setError(error);

            } else {//remote
                const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
                if (error < NO_ERROR) reply.setError(error);
            }

三、Java层类

Java层的类主要有Binder和BinderProxy,其中Binder跟BBinder一样,属于Server或Local端,而BinderProxy则与BpBinder一样,属于Client端或Remote端。

 

对于BinderProxy类对象,跟BpBinder一样,同样是作为XXXProxy的成员变量的形式包含于其中。

 

XXXProxy --> IXXX --> IInterface.

 

在JNI层,定义了两个转换函数:

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

sp<IBinder>ibinderForJavaObject(JNIEnv* env, jobject obj);

上述两种函数提供了Java对象(主要是Binder和BinderProxy对象)与Native层IBinder对象之间的相互转换接口。


当我们调用transact方法时,会经历如下一些过程:

 

in BinderProxy.java

public native boolean transact(int code,Parcel data, Parcel reply,

           int flags) throws RemoteException;

-->

in android_util_Binder.cpp

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
     …
    IBinder* target = (IBinder*)
        env->GetIntField(obj, gBinderProxyOffsets.mObject);
    …
    //printf("Transact from Java code to %p sending: ", target); data->print();
    status_t err = target->transact(code, *data, reply, flags);
    …
    return JNI_FALSE;
}

其中gBinderProxyOffsets.mObject是通过javaObjectForIBinder设置的,它的原型如下:

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

对于上述函数,除非参数val是JavaBBinder(继承自BBinder)对象,否则,就创建一个BinderProxy对象,它与一个BpBinder对象关联。

-->

接下来就会调用某个IBinder(C++类)对象的transact方法。

这个IBinder对象是BpBinder类型的,即:

BpBinder::transact(…)

--> IPCThreadState::transact(…)


它会向Binder驱动发送一个BC_TRANSACTION命令,Binder驱动进行处理,将请求路由给通信的另一端,并通过命令BR_TRANSACTION告知用户空间,有新的通信请求。在介绍BBinder的时候,我们提到过,接收端会调用BBinder::transact(…)来处理请求,对于Java层的通信来说,则会实际调用JavaBBinder::transact(…)来处理请求,而实际上会调用onTransact(…)(重载了BBinder的方法),如下所示:


class JavaBBinder : public BBinder
{
…
protected:
…

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

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

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

       …
    }

…
};

-->

in Binder.java

// Entry point from android_util_Binder.cpp's onTransact
    private boolean execTransact(int code, int dataObj, int replyObj,
            int flags) {
        …
        boolean res;
        try {
            res = onTransact(code, data, reply, flags);
        } …

        return res;
    }

最终调用到了Binder类的onTransact方法。从Binder类派生的类都会重载该方法。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值