您的位置:首页 > 其它

如何使用Binder实现分析

2014-03-05 18:11 671 查看
看了老罗的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;
}
}


BpInterface<IXXX>的继承关系定义在IInterface中

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;
}


to be continued..
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐