文章目录
- 1. 规范制定者 IInterface.h
- 1. 客户端规范
- 2. 服务端规范
- 3. 两个重要的宏
- 2. 以AudioFlinger为例
- 1. 客户端 IAudioFlinger
- 2. 服务端 AudioFlinger
- 3. 总结
本文以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’开头加上传入的接口变量来做声明/实现
-
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(); \
-
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()函数;