如何使用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的入口
定义XXX接口
XXX接口是和XXX服务相关,例如提供getXXX , setXXX函数,和应用逻辑相关。
需要从IInterface派生
我们声明了一个 DECLARE_META_INTERFACE(XXX) 的宏,他的定义在IInterface.h中,展开看看
这样我们有多了几个方法....继续
为了把IXXX加入到Binder结构中去,需要定义BnXXX和对客户端透明的BpXXX。
既然要透明我们就要把BpXXX放在cpp中实现。
BnXXX是需要头文件的,可以把它和IXXX定义放在一块,分开也行,我们把他放入一个文件IXXX.h
文件中。
继承BnInterface<IXXX>是继承什么,他的定义同样在IInterface中。
兑现后为
接着我们在某个CPP中实现他们,IXXX.cpp :
IMPLEMENT_META_INTERFACE(XXX,"");定义在IInterface中。
展开并兑现了看看...
这样已兑现,该实现的都实现了,就只剩getXXX(), setXXX()应用逻辑需要我们实现。一个宏声明,一个宏实现,我们就把Binder接入自己的程序了,省去了很多步啊, 继续啊...
我们在asInterfance中看到,new Bp##INTERFACE(obj), 这个就是Client的获得proxy对象了,用来封装参数IPC到我们的进程中,它也实现在IXXX.cpp 文件中。
BpInterface<IXXX>的继承关系定义在IInterface中
兑现为:
到此为止我们就已经实现了自己定义的Service.
Client通过ServiceManager查询出我们的就可以调用我们提供的服务了
to be continued..
分析媒体框架发现,我们要实现一个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..
相关文章推荐
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(1)
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(2)
- 如何使用androidpn实现android手机消息推送(简单的源码分析)
- 如何使用androidpn实现android手机消息推送(简单的源码分析)
- 如何使用androidpn实现android手机消息推送(简单的源码分析)
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(1)
- 关于如何使用block实现和协议一样的功能分析
- Ajax详解及其案例分析之如何获得Ajax对象,使用Ajax对象发送GET和POST请求,校验用户名,POST和GET请求时的乱码处理,实现级联的下拉列表
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(2)
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(2)
- 如何实现日志的集中化存储以及使用loganalyzer做日志分析 推荐
- 【源代码】手把手教你Autolayout如何使用动画(附类似Passbook效果Demo+详细分析实现原理)
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(1)
- 如何整合Spring和Mybatis的思路分析(使用面向接口的mapper代理,不用再去写Dao的实现类)
- Binder机制分析(2)——从MediaService中看Binder的实现和使用(1)
- 如何使用androidpn实现android手机消息推送(简单的源码分析)
- dedecsm模板中首页如何实现分页的三种方法比较分析
- spring中如何使用quartz实现定时作业
- 小马分享(如何使用Spring实现读写分离(MySQL实现主从复制))
- 如何使用 jstack 分析线程状态