看了老罗的Binder源码分析实在是有点难懂,驱动的分析因为没有基础所以看起来很吃力,但android在native层给我们封装了快速实现Binder应用的库,在此记录,以作查用。
分析媒体框架发现,我们要实现一个IPC服务,大体可以总结为以下几步。
1、获得ServiceManager。
2、实现Service并把自己加入ServiceManager中。
3、进入等待,并接受Client的请求。
其中大多的方法和实现Android都有现成的可以调用,我们只要实现第2步,即实现自己Service。
下面我们就具体实践:
首先肯定会有一个C++程序,类似于main_MediaService的入口
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
MediaPlayerService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
定义XXX接口
XXX接口是和XXX服务相关,例如提供getXXX , setXXX函数,和应用逻辑相关。
需要从IInterface派生
class IXXX: public IInterface
{
public:
DECLARE_META_INTERFACE(XXX);申明宏
virtual getXXX() = 0;
virtual setXXX() = 0;
}这是一个接口。
我们声明了一个 DECLARE_META_INTERFACE(XXX) 的宏,他的定义在IInterface.h中,展开看看
class IXXX: public IInterface
{
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();
virtual getXXX() = 0;
virtual setXXX() = 0;
}
这样我们有多了几个方法....继续
为了把IXXX加入到Binder结构中去,需要定义BnXXX和对客户端透明的BpXXX。
既然要透明我们就要把BpXXX放在cpp中实现。
BnXXX是需要头文件的,可以把它和IXXX定义放在一块,分开也行,我们把他放入一个文件IXXX.h 文件中。
class BnXXX: public BnInterface<IXXX>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
//由于IXXX是个纯虚类,而BnXXX只实现了onTransact函数,所以BnXXX依然是一个纯虚类
};
继承BnInterface<IXXX>是继承什么,他的定义同样在IInterface中。
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();
};
兑现后为
class BnXXX: public IXXX, public BBinder
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data, Parcel* reply, uint32_t flags = 0);//这样BnXXX就拥有了IXXX以下的方法:
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();
virtual getXXX() = 0;
virtual setXXX() = 0;
};
接着我们在某个CPP中实现他们,IXXX.cpp :
IMPLEMENT_META_INTERFACE(XXX, "android.xxx.IXXX");//IMPLEMENT宏
status_t BnXXX::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case GET_XXX: {
CHECK_INTERFACE(IXXX, data, reply);
//读请求参数
//调用虚函数getXXX()
return NO_ERROR;
} break;
case SET_XXX: {
CHECK_INTERFACE(IXXX, data, reply);
//读请求参数
//调用虚函数getXXX()
return NO_ERROR;
}
}
IMPLEMENT_META_INTERFACE(XXX,"");定义在IInterface中。
展开并兑现了看看...
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 != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { }
status_t BnXXX::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code)
{
...
}
}
这样已兑现,该实现的都实现了,就只剩getXXX(), setXXX()应用逻辑需要我们实现。一个宏声明,一个宏实现,我们就把Binder接入自己的程序了,省去了很多步啊, 继续啊...
我们在asInterfance中看到,new Bp##INTERFACE(obj), 这个就是Client的获得proxy对象了,用来封装参数IPC到我们的进程中,它也实现在IXXX.cpp 文件中。
class BpXXX: public BpInterface<IXXX>
{
public:
BpXXX (const sp<IBinder>& impl): BpInterface< IXXX >(impl) //定义调用父类的构造
{
}
vitural getXXX()
{
Parcel data, reply;
data.writeInterfaceToken(IXXX::getInterfaceDescriptor());
data.writeInt32(pid); remote()->transact(GET_XXX, data, &reply);
return;
}
vitural setXXX()
{
Parcel data, reply;
data.writeInterfaceToken(IXXX::getInterfaceDescriptor());
data.writeInt32(pid);
remote()->transact(SET_XXX, data, &reply);
return;
}
}
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
兑现为:
class BpXXX: public IXXX, BpRefBase
{
public:
BpXXX (const sp<IBinder>& impl): BpInterface<IXXX>(impl)
{ //调用父类BpInterface构造,BpInterface又调用父类BpRefBase的构造(这层实现是通过IInterface 的内联函数重载了的), BpRefBase只是简单的把 imp 保存在自己的成员变量中mRemote, 子类可以调用他的remote()函数把他返回出来,另作他用
}
vitural getXXX() //继承自 IXXX方法
{
...
remote()->transact(GET_XXX, data, &reply);
...
}
vitural setXXX() //继承自 IXXX方法
{
...
remote()->transact(SET_XXX, data, &reply);
...
}
protected:
virtual IBinder* onAsBinder(); //实现与IInterface 内联函数,只是调用父类BpRefBase.remote()返回 impl对象
}
到此为止我们就已经实现了自己定义的Service.
Client通过ServiceManager查询出我们的就可以调用我们提供的服务了
XXXClient::getService()
{
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("android.xxx.IXXX"));
sp<IXXX> service = interface_cast<IXXX>(binder); //interface_cast<IXXX>(binder) 等于 IXXX.asInterface(binder) , 定义在IInterface
return service;
}