参考:

The Android binderfs Filesystem — The Linux Kernel documentation

前言:

Android Binder 是一种 IPC 机制,IPC 键值/标识 是一个字符串,收发双方通过 键值/标识 建立通讯路径。

Binder 是通过模板类实现的,因此使用起来并不是那么简明通俗,如果没有demo可以参考的话是需要琢磨好一阵子。

相关头文件:

//  \frameworks\native\include\binder\IInterface.h
#include <binder/IInterface.h>
//  \frameworks\native\include\binder\IBinder.h
#include <binder/IBinder.h>

重要的类:

class IInterface 

IPC 的收发双方需要约定交互接口,因此收发双方都需要通过某种方式集成这个类,一般情况下会定义一个类来继承IInterface,然后收发双方再通过类模板的方式对新定义的接口类做集成。

//  \frameworks\native\include\binder\IInterface.h
class IInterface : public virtual RefBase
{
public:
            IInterface();
            static sp<IBinder>  asBinder(const IInterface*);
            static sp<IBinder>  asBinder(const sp<IInterface>&);

protected:
    virtual                     ~IInterface();
    virtual IBinder*            onAsBinder() = 0;          //需要子类实现
};

//  \frameworks\native\libs\binder\IInterface.cpp
IInterface::IInterface() 
    : RefBase() {
}

IInterface::~IInterface() {
}

// static
sp<IBinder> IInterface::asBinder(const IInterface* iface)
{
    if (iface == nullptr) return nullptr;
    return const_cast<IInterface*>(iface)->onAsBinder();
}

// static
sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
{
    if (iface == nullptr) return nullptr;
    return iface->onAsBinder();
}

class BpInterface

BpInterface 是模板类,他继承自一个 IInterface 的子类,同时也继承 BBinder,如果我们实现 Binder的 Client 端,则可以使用这个类作为父类。

//  \frameworks\native\include\binder\IInterface.h
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
    explicit                    BpInterface(const sp<IBinder>& remote);

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
};

template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
{
}

template<typename INTERFACE>
inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
    return remote();
}

前面说到 IInterface 的 onAsBinder 为纯虚函数,这里 BpInterface 就实现了这个纯虚函数,通过调用父类 BpRefBase 的 remote() 方法返回一个 IBinder。

//  \frameworks\native\include\binder\Binder.h
class BpRefBase : public virtual RefBase
{
protected:
    explicit                BpRefBase(const sp<IBinder>& o);
    virtual                 ~BpRefBase();
    virtual void            onFirstRef();
    virtual void            onLastStrongRef(const void* id);
    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);

    inline  IBinder*        remote()                { return mRemote; }
    inline  IBinder*        remote() const          { return mRemote; }

private:
                            BpRefBase(const BpRefBase& o);
    BpRefBase&              operator=(const BpRefBase& o);

    IBinder* const          mRemote;
    RefBase::weakref_type*  mRefs;
    std::atomic<int32_t>    mState;
};

class BnInterface

BnInterface 和 BpInterface 类似,它一般用作 Binder Server 端。区别在于切换至 IBinder 角色的方法不一样,Bp是 return remote() ,Bn 是直接返回自己。

template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
};

template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
        const String16& _descriptor)
{
    if (_descriptor == INTERFACE::descriptor) return this;
    return nullptr;
}

template<typename INTERFACE>
inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const
{
    return INTERFACE::getInterfaceDescriptor();
}

template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
    return this;
}

BnInterface 是继承自 BBinder 的,这个类规定了作为 Binder 服务端应该具备哪些特质,一般情况下我们需要重写 onTransact 函数以完成我们自己的消息处理逻辑。

class BBinder : public IBinder
{
public:
                        BBinder();

    virtual const String16& getInterfaceDescriptor() const;
    virtual bool        isBinderAlive() const;
    virtual status_t    pingBinder();
    virtual status_t    dump(int fd, const Vector<String16>& args);

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
                                    void* cookie = nullptr,
                                    uint32_t flags = 0);

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    unlinkToDeath(  const wp<DeathRecipient>& recipient,
                                        void* cookie = nullptr,
                                        uint32_t flags = 0,
                                        wp<DeathRecipient>* outRecipient = nullptr);

    virtual void        attachObject(   const void* objectID,
                                        void* object,
                                        void* cleanupCookie,
                                        object_cleanup_func func);
    virtual void*       findObject(const void* objectID) const;
    virtual void        detachObject(const void* objectID);

    virtual BBinder*    localBinder();

    bool                isRequestingSid();
    // This must be called before the object is sent to another process. Not thread safe.
    void                setRequestingSid(bool requestSid);

protected:
    virtual             ~BBinder();

    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);

private:
                        BBinder(const BBinder& o);
            BBinder&    operator=(const BBinder& o);

    class Extras;

    Extras*             getOrCreateExtras();

    std::atomic<Extras*> mExtras;
            void*       mReserved0;
};

Demo

DemoInterface.h

#include <binder/IInterface.h>

// 一定要是I 开头
class IDemo : public IInterface {

//  client use
  enum {
     MSG_1,
     MSG_2,
     MSG_3,
     MSG_CNT
  }
  //  通过虚函数强制要求client实现,client通过下面这几个函数里向server侧发送MSG,并同步等待应答
  virtual void postMSG1(int i) = 0;  //带参数,组装到 MSG 里面发送给server
  virtual void postMSG2() = 0;
  virtual int postMSG3() = 0;  //可以是有返回值的

  DECLARE_META_INTERFACE(Demo);  //对应类名 I 之后的那部分
  IMPLEMENT_META_INTERFACE(Demo,"Demo"); //实现部分
}

BpDemo.h

#include "DemoInterface.h"

class BpDemo : public BpInterface<IDemo> 
{
public:
   //BpInterface本身没有默认构造函数,所以只能使用唯一的一个构造函数来构造,
   //这个构造函数接受一个IBinder指针作为输入,这个IBinder指向一个Binder对象,
   //所以我们实现的其子类 BpDemo 也必须有一个接受 IBinder 指针入参的构造函数来
   //构造其父类 BpInterface, 并且需要用这个 IBinder 指针构造 BpInterface。
   //
   // 小结 : 作为client侧,需要在构造的时候就知道 server 侧对应的那个 Binder是什么,这很合理
   //
   BpDemo(const sp<IBinder>& impl)
     :BpInterface<IDemo>(impl) 
   {

   }
   virtual ~BpDemo() {;}

   //必须实现IDemo中的纯虚函数
   virtual void postMSG1(int i){
      Parcel data, replay;
      //写Binder的键值(token)
      data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
      data.writeInt32(i); //写需要传输的字段

      //使用BpInterface父类的remote()方法获取BBinder对象,调用transact()传输MSG
      remote()->transact(MSG1,data,&reply);
   }

   virtual void postMSG1(){
      Parcel data, replay;
      data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
      remote()->transact(MSG2,data,&replay,IBinder::FLAG_ONEWAY); //异步
   }

   virtual int postMSG3(){
      Parcel data, replay;
      data.writeInterfaceToken(IDemo::getInterfaceDescriptor());
      remote()->transact(MSG3,data,&replay);
      int ret;
      reply.readInt32(ret);    //
      return ret;
   }

}


/*
BpInterface<IDemo> 展开为

class BpInterface : public IDemo, public BpRefBase
{
public:
    explicit         BpInterface(const sp<IBinder>& remote);

protected:
    typedef IDemo           BaseInterface;
    virtual IBinder*        onAsBinder();
};
*/