设计思路
基于代理的思想,用户无需关心底层实现细节,驱动层实现了内存一次拷贝以及FD、Binder句柄的传递
接口设计
IBinder:transact、remoteBinder、localBinder、queryLocalInterface
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;
};
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>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
explicit BpInterface(const sp<IBinder>& remote);
protected:
typedef INTERFACE BaseInterface;
virtual IBinder* onAsBinder();
};
#define DECLARE_META_INTERFACE(INTERFACE) \
public: \
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(); \
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const ::android::String16 I##INTERFACE::descriptor(NAME); \
const ::android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
if (obj != nullptr) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == nullptr) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
class IAudioManager : public IInterface
{
public:
DECLARE_META_INTERFACE(AudioManager)
virtual audio_unique_id_t trackPlayer(player_type_t playerType) = 0;
/*oneway*/ virtual status_t releasePlayer(audio_unique_id_t piid) = 0;
virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) = 0;
/*oneway*/ virtual status_t releaseRecorder(audio_unique_id_t riid) = 0;
};
class BpAudioManager : public BpInterface<IAudioManager>
{
public:
explicit BpAudioManager(const sp<IBinder>& impl)
: BpInterface<IAudioManager>(impl)
{
}
...
}
IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
驱动原理
BpBinder -> handle -> binder_ref -> binder_node -> BBinder
涉及到Flat_binder数据结构(Binder、FD),内核自动转换
ProcessState
打开Binder驱动文件、设置mmap共享内存(1M - 8K)、保存进程内的所有BpBinder对象、扩展Binder线程
IPCThreadState
使用ioctl和驱动通信:常见的协议格式有:
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, int64_t)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t)
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, int)
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
#define BINDER_THREAD_EXIT _IOW('b', 8, int)
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
其中还涉及到BC、BR命令,以及是否等待的逻辑(BR_TRANSACTION_COMPLETE、BR_REPLY)
一次拷贝原理
mmap时,内核保存各个进程的地址控件和内核空间的对应关系,当执行数据传递时,发送端会将数据写入到目标进程对应的内核控件,然后根据偏移量返回目标进程的用户空间地址
匿名内存原理
进程A打开ashmem驱动并获取到FD,当通过Binder传递对应FD时,驱动会在目标进程空间创建指向相同文件节点的句柄。当执行mmap时,如果没有创建file文件,则创建对应文件,如果已创建则复用,然后将vm_area_struct的vm_file指针指向真正操作的file
Binder线程
RuntimeInit.zygoteInit时初始化Binder环境:
nativeZygoteInit();
virtual void onZygoteInit() {
sp proc = ProcessState::self();
//启动新binder线程loop
proc->startThreadPool();
}
applicationInit(targetSdkVersion, argv);