参考:
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文章来源:https://www.toymoban.com/news/detail-546401.html
#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文章来源地址https://www.toymoban.com/news/detail-546401.html
#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();
};
*/
到了这里,关于[DEMO] Android Binder 的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!