Android C++层使用Binder通信的方法

本文以Audio系统为例,基于Android 7.1

1. 规范制定者 IInterface.h

IInterface.h是C++层Binder通信的规范定制者, 客户端和服务端都要包含该头文件。
IInterface.h中提供了C++层Binder通信必要的工具。

1. 客户端规范

客户端需要继承BpInterface 和IInterface,这个是个模板类,作用其实是使客户端对象继承自模板对象,如下:

//frameworks/native/include/binder/IInterface.h

//IInterface 中定义了对Binder的转换操作
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;
};

//BpInterface 
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase //**BpRefBase 中有个remote()函数,
                                                      //直接指向服务端Bind而对象
{
public:
                                //remote使服务端Binder对象
                                BpInterface(const sp<IBinder>& remote);

protected:
    virtual IBinder*            onAsBinder();
};

BpRefBase

BpRefBase 继承自RefBase,所以在首次引用的时候会调用onFirstRef方法

//frameworks/native/include/binder/Binder.h
class BpRefBase : public virtual RefBase
{
protected:
                            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);

                            //remote()函数直接使用,就是代表了服务端对象
    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;
};

//构造实现
BpRefBase::BpRefBase(const sp<IBinder>& o)
    //mRemote来自子类的传递
    : mRemote(o.get()), mRefs(NULL), mState(0)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

    if (mRemote) {
        mRemote->incStrong(this);           // Removed on first IncStrong().
        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
    }
}

2. 服务端规范

服务端要继承BnInterface ,这个是个模板类,作用其实是使服务端对象继承自模板对象,如下:

//frameworks/native/include/binder/IInterface.h
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();
};

3. 两个重要的宏

Android提供的这两个宏是方便Binder接口的统一实现
需要以‘I’开头加上传入的接口变量来做声明/实现

  1. DECLARE_META_INTERFACE: 声明接口构造
#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();                                            \
  1. IMPLEMENT_META_INTERFACE:
    实现接口构造(和DECLARE_META_INTERFACE声明对应,实现其声明的接口构造和变量)
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    //descriptor是客户端和服务端的对接标识符,以传入的NAME作为初始化内容
    const android::String16 I##INTERFACE::descriptor(NAME);             \
    const android::String16&                                            \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    //服务端的Binder对象是通过接口的asInterface传入的,所以在找服务端接口的时候,可以使用
    //I##INTERFACE::asInterface来查找
    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) {                                         \
                //创建客户端对象,传入服务端Binder对象
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \
    
    ---------------------------------------------------------------------------------------
	//一个方便的函数,将Binder对象转换为对应的客户端接口
	template<typename INTERFACE>
	inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
	{
	    return INTERFACE::asInterface(obj);//也是调用对应模板的asInterface方法的
	}

2. 以AudioFlinger为例

1. 客户端 IAudioFlinger

//frameworks/av/include/media/IAudioFlinger.h
class IAudioFlinger : public IInterface
{
public:
    DECLARE_META_INTERFACE(AudioFlinger);//声明宏
}

//服务端实现接口的规范
class BnAudioFlinger : public BnInterface<IAudioFlinger>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};
//frameworks/av/media/libmedia/IAudioFlinger.cpp
class BpAudioFlinger : public BpInterface<IAudioFlinger>
{
public:
    BpAudioFlinger(const sp<IBinder>& impl)
        : BpInterface<IAudioFlinger>(impl)//这里的构造中的Binder对象是在上面的
                                         //IMPLEMENT_META_INTERFACE宏中传入的
    {
    }
    IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
}

获取IAudioFlinger服务端的例子:

//frameworks/av/media/libmedia/AudioSystem.cpp
const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
{
    sp<IAudioFlinger> af;
    sp<AudioFlingerClient> afc;
    {
        Mutex::Autolock _l(gLock);
        if (gAudioFlinger == 0) {
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
               //获取AudioFlinger Binder对象
                binder = sm->getService(String16("media.audio_flinger"));
                if (binder != 0)
                    break;
                ...
            } while (true);
            ...
            //转化为IAudioFlinger 接口,作为服务端代理
            gAudioFlinger = interface_cast<IAudioFlinger>(binder);
            ...
        }
        af = gAudioFlinger;
    }
    ...
    return af;
}

客户端信息总结:

  • 客户端接口: IAudioFlinger
  • 客户端d代理对象: BpAudioFlinger
  • descriptor: android.media.IAudioFlinger
  • 服务端: AudioFlinger
  • remote() : 即服务端 AudioFlinger

2. 服务端 AudioFlinger

//frameworks/av/services/audioflinger/AudioFlinger.h
class AudioFlinger :
    public BinderService<AudioFlinger>, //这个接口会将AudioFlinger 注册到ServiceManager中
    public BnAudioFlinger //继承自BnInterface
{
    friend class BinderService<AudioFlinger>;   // for AudioFlinger()
public:
    //服务端在ServiceManager注册的时候的服务账号,客户端用这个账号从ServiceManager中获取服务端Binder对象。
    static const char* getServiceName() ANDROID_API { return "media.audio_flinger"; }
}

服务端信息总结

  • 服务端接口: IAudioFlinger (和客户端对应,这样才转换为客户端接口IAudioFlinger)
  • 服务端对象:AudioFlinger
  • 服务注册账号: media.audio_flinger

3. 总结

  • 客户端文件需要Include IInterface.h 文件, 客户端需要继承自IInterface接口,这个接口主要规定了一些对Binder的转换操作;
  • 客户端中的remote()函数指的是服务端在客户端的接口代理(I##INTERFACE),调用直接到服务端的onTransact()函数中;
  • 客户端继承规则: public Bp##INTERFACE : public I##INTERFACE : public IInterface
  • 服务端继承规则: (INTERFACE : ) public Bn##INTERFACE: public I##INTERFACE : public IInterface
  • 服务端需要继承自Bn##INTERFACE接口,在获取服务端之后使用inerface_cast接口或者I##INTERFACE::asInterface转换为客户端接口I##INTERFACE,在客户端直接使用的体现是remote()函数
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其中的binder是重中之重,都说无binderAndroidbinde是Android系统的任督二脉。课程水平循序渐进,由中级再到高级,满足各个次水平的android开发者。1、灵活使用binder跨进程通信,在app端对它的任何api方法使用自如2、可以单独分析android系统源码中任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上的java app端一直到最底的内核binder驱动,都可以顺利理通5、针对系统开发过程中遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码中使用的socket源码轻松掌握9、android系统源码中最常见的socketpair中双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序
binder c是指在Android系统中使用C语言编写的binder代码实现。它可以通过添加内存共享、读写通知来实现binder通信。在Android 9上经过测试并没有问题。[1] 在Android系统中,binder的作用是配接函数对象,形成新的函数对象,调用全局函数针对对象、对象指针、智能对象指针调用成员函数。它可以用于使用C标准库预定义的函数对象时指定参数。 对于Android系统而言,binder机制是常见的,也是初学者最难搞明白的部分,很多Service都是通过binder机制与客户端进行通讯交互的。理解binder的机制可以帮助我们更好地理解程序运行的流程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Android binder C++ service/client 实现. 共享内存](https://download.csdn.net/download/jounehou/12915968)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [C++函数适配器Binder](https://blog.csdn.net/weixin_44048823/article/details/93380331)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C++使用binder实例](https://blog.csdn.net/weixin_30293079/article/details/95537179)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值