使用C++自定义Binder
2015-11-24 15:13
453 查看
参考Binder使用示例学习一下binder。
Binder的核心类关系见下图:
红框内是需要开发自定义binder时自己定义的,其中:
1).Binder实体对象:Binder服务的提供者,继承自BBinder。
2).Binder引用对象:Binder实体对象在客户进程的代表。
3).Binder代理对象:为客户端的上层应用提供接口服务,通过代理对象,应用可以像使用本地对象一样使用远端实体对象的服务。
使用C++开发Binder服务:
1)定义用户自定义接口,C++中需要使用抽象基类和纯虚函数来实现。这些函数接口统一了客户端和服务端的函数调用。
声明BnTestBinderService,它必须要继承模板类BnInterface<>;该模板类继承了BBinder和ITestBinderService。
2)定义BpTestBinderService并实现BnTestBinderService的虚函数onTransact()。这两个类运行的在不同的进程中,但需要把他们定义在同一个文件中。这是因为:它们使用了相同的函数码和类的描述字串,如果分开定义需要定义两份函数名和描述字串。
BpTestBinderService继承了模板类BpInterface<>,BpInterface<>继承了ITestBinderService和BpRefBase;ITestBinderService定义了binder服务接口,BpRefBase聚合了一个binder引用对象BpBinder;因此BpTestBinderService成为了binder代理。BpTestBinderService使用ITestBinderService定义了binder服务函数把函数调用信息发送给服务端,服务端收到信息后使用相同的服务函数接口并返回服务结果,以此完成一次进程间通信。本例中BpTestBinderService使用add函数把需要的函数参数发送给服务端,服务端返回add服务结果。BpTestBinderService的add实现过程为:首先把类的描述字串放到Parcel中,接着把调用的参数依次放入,最后通过调用remote()函数得到binder引用对象的指针,并调用该引用对象的transact()函数把数据传递给底层,BpBinder的transact实现,就是直接调用IPCThreadState::self()->transact()发送数据。
BnTestBinderService只需要实现onTransact()。当IPCThreadState接收到client的请求后,首先会调用BBinder的transact函数;然后BBinder的transact函数就会调用子类实现的onTransact。
onTransact()函数实现比较标准化,根据参数中的函数码(第一个形参code)调用相应的服务,每个服务的写法也很固定:首先调用 CHECK_INTERFACE宏检查Parcel对象中的数据是否正确,检查原理是取出Parcel对象中从客户端传递过来的类描述字串,并和类中定义的字串相比较,看是否相同。接着按照函数参数的顺序取出参数,并使用这些参数调用服务端的函数(由BnTestBinderService的子类实现)。调用结束后通过reply对象把函数的返回值传回去。
由此可以看出BBinder、BnTestBinderService、BpBinder、BpTestBinderService在通信层面各自的作用为:
BBinder、BnTestBinderService接收IPCThreadState传递过来的信息,解包数据,并调用ITestBinderService定义的服务接口在服务端真正的实现。
BpTestBinderService用来打包数据,BpBinder发送数据给IPCThreadState。
IMPLEMENT_META_INTERFACE(TestBinderService, "android.test.ITestBinderService");
对于这个宏是ITestBinderService中声明的IMPLEMENT_META_INTERFACE实现,宏展开如下:
它添加了静态成员变量 descriptor、静态函数asInterface以及ITestBinderService类的构造函数和析构函数。其中descriptor描述了自定义binder服务接口信息,检查从客户端传递参数是否合法时需要用到它。对于asInterface函数,如果在客户端进程中调用,则会创建一个binder代理对象,代理对象包含了引用对象;如果在服务端进程中调用,直接返回参数的指针,因为服务端可以直接调用服务类,无须创建代理。
3)定义自定义服务类TestBinderService,该类继承BnTestBinderService 。TestBinderService实现了服务端的add服务,并且定义了一个静态函数instantiate(),该函数把自定义的binder服务加载到binder服务列表中。
4)启动服务端。
5)客户端中使用binder服务。
Binder的核心类关系见下图:
红框内是需要开发自定义binder时自己定义的,其中:
1).Binder实体对象:Binder服务的提供者,继承自BBinder。
2).Binder引用对象:Binder实体对象在客户进程的代表。
3).Binder代理对象:为客户端的上层应用提供接口服务,通过代理对象,应用可以像使用本地对象一样使用远端实体对象的服务。
使用C++开发Binder服务:
1)定义用户自定义接口,C++中需要使用抽象基类和纯虚函数来实现。这些函数接口统一了客户端和服务端的函数调用。
class ITestBinderService: public IInterface { public: DECLARE_META_INTERFACE(TestBinderService); virtual int add(int a, int b) = 0; };
声明BnTestBinderService,它必须要继承模板类BnInterface<>;该模板类继承了BBinder和ITestBinderService。
class BnTestBinderService: public BnInterface<ITestBinderService> { public: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); };
2)定义BpTestBinderService并实现BnTestBinderService的虚函数onTransact()。这两个类运行的在不同的进程中,但需要把他们定义在同一个文件中。这是因为:它们使用了相同的函数码和类的描述字串,如果分开定义需要定义两份函数名和描述字串。
BpTestBinderService继承了模板类BpInterface<>,BpInterface<>继承了ITestBinderService和BpRefBase;ITestBinderService定义了binder服务接口,BpRefBase聚合了一个binder引用对象BpBinder;因此BpTestBinderService成为了binder代理。BpTestBinderService使用ITestBinderService定义了binder服务函数把函数调用信息发送给服务端,服务端收到信息后使用相同的服务函数接口并返回服务结果,以此完成一次进程间通信。本例中BpTestBinderService使用add函数把需要的函数参数发送给服务端,服务端返回add服务结果。BpTestBinderService的add实现过程为:首先把类的描述字串放到Parcel中,接着把调用的参数依次放入,最后通过调用remote()函数得到binder引用对象的指针,并调用该引用对象的transact()函数把数据传递给底层,BpBinder的transact实现,就是直接调用IPCThreadState::self()->transact()发送数据。
class BpTestBinderService: public BpInterface<ITestBinderService> { public: BpTestBinderService(const sp<IBinder>& impl) : BpInterface<ITestBinderService> (impl) { } int add(int a, int b) { Parcel data, reply; printf("Enter BpTestBinderService add,a = %d , b = %d\n", a, b); data.writeInterfaceToken(ITestBinderService::getInterfaceDescriptor()); data.writeInt32(a); data.writeInt32(b); remote()->transact(TEST_ADD, data, &reply); int sum = reply.readInt32(); printf("BpTestBinderService sum = %d\n", sum); return sum; } }; IMPLEMENT_META_INTERFACE(TestBinderService, "android.test.ITestBinderService"); // ---------------------------------------------------------------------- status_t BnTestBinderService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case TEST_ADD: { CHECK_INTERFACE(ITestBinderService, data, reply); int a = data.readInt32(); int b = data.readInt32(); printf("Enter BnTestBinderService add,a = %d , b = %d\n", a, b); int sum = 0; sum = add(a, b); printf("BnTestBinderService sum = %d\n", sum); reply->writeInt32(sum); return sum; } default: return BBinder::onTransact(code, data, reply, flags); } }
BnTestBinderService只需要实现onTransact()。当IPCThreadState接收到client的请求后,首先会调用BBinder的transact函数;然后BBinder的transact函数就会调用子类实现的onTransact。
onTransact()函数实现比较标准化,根据参数中的函数码(第一个形参code)调用相应的服务,每个服务的写法也很固定:首先调用 CHECK_INTERFACE宏检查Parcel对象中的数据是否正确,检查原理是取出Parcel对象中从客户端传递过来的类描述字串,并和类中定义的字串相比较,看是否相同。接着按照函数参数的顺序取出参数,并使用这些参数调用服务端的函数(由BnTestBinderService的子类实现)。调用结束后通过reply对象把函数的返回值传回去。
由此可以看出BBinder、BnTestBinderService、BpBinder、BpTestBinderService在通信层面各自的作用为:
BBinder、BnTestBinderService接收IPCThreadState传递过来的信息,解包数据,并调用ITestBinderService定义的服务接口在服务端真正的实现。
BpTestBinderService用来打包数据,BpBinder发送数据给IPCThreadState。
IMPLEMENT_META_INTERFACE(TestBinderService, "android.test.ITestBinderService");
对于这个宏是ITestBinderService中声明的IMPLEMENT_META_INTERFACE实现,宏展开如下:
#define IMPLEMENT_META_INTERFACE(TestBinderService, "android.test.ITestBinderService") \ const android::String16 ITestBinderService::descriptor("android.test.ITestBinderService"); \ const android::String16& \ ITestBinderService::getInterfaceDescriptor() const { \ return ITestBinderService::descriptor; \ } \ android::sp<ITestBinderService> ITestBinderService::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<ITestBinderService> intr; \ if (obj != NULL) { \ intr = static_cast<ITestBinderService*>( \ obj->queryLocalInterface( \ ITestBinderService::descriptor).get()); \ if (intr == NULL) { \ intr = new BpTestBinderService(obj); \ } \ } \ return intr; \ } \ ITestBinderService::ITestBinderService() { } \ ITestBinderService::~ITestBinderService() { }
它添加了静态成员变量 descriptor、静态函数asInterface以及ITestBinderService类的构造函数和析构函数。其中descriptor描述了自定义binder服务接口信息,检查从客户端传递参数是否合法时需要用到它。对于asInterface函数,如果在客户端进程中调用,则会创建一个binder代理对象,代理对象包含了引用对象;如果在服务端进程中调用,直接返回参数的指针,因为服务端可以直接调用服务类,无须创建代理。
3)定义自定义服务类TestBinderService,该类继承BnTestBinderService 。TestBinderService实现了服务端的add服务,并且定义了一个静态函数instantiate(),该函数把自定义的binder服务加载到binder服务列表中。
class TestBinderService: public BnTestBinderService { public: static void instantiate(); int add(int a,int b); private: TestBinderService(); virtual ~TestBinderService(); };
<pre name="code" class="cpp">void TestBinderService::instantiate() { printf("Enter TestBinderService::instantiate\n"); status_t st = defaultServiceManager()->addService( String16("my.test.binder"), new TestBinderService());//定义binder服务字串并加入binder服务列表 printf("ServiceManager addService ret=%d\n", st); printf("instantiate> end\n"); } TestBinderService::TestBinderService() { printf(" TestBinderServicet"); } TestBinderService::~TestBinderService() { printf("TestBinderService destroyed,never destroy normally"); } int TestBinderService::add(int a,int b) { printf("TestBinderService::add a = %d, b = %d.", a , b); return a+b; }
4)启动服务端。
sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); printf("before TestBinderService start\n"); TestBinderService::instantiate(); printf("TestBinderService End\n"); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool();
5)客户端中使用binder服务。
sp<ITestBinderService> mTestBinserService; if (mTestBinserService.get() == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; binder = sm->getService(String16("my.test.binder"));//使用与服务端统一的binder服务描述字串 mTestBinserService = interface_cast<ITestBinderService> (binder); if (mTestBinserService == 0) printf("no ITestBinserService!?\n"); } sum = mTestBinserService->add(3, 4);
相关文章推荐
- C++primer plus第六版课后编程练习答案2.6
- C++primer plus第六版课后编程练习答案2.4
- C++ - 隐式类类型转换
- C++primer plus第六版课后编程练习答案2.3
- qt下bezier曲线的绘制(C++)
- C++primer plus第六版课后编程练习答案2.2
- C++primer plus第六版课后编程题练习答案2.1
- C/C++——友元函数
- C++先,中,后顺序遍历的非递归实现
- C++之日志打印
- 第一章:C语言数据类型
- C语言-----循环单链表
- PVS-Studio C/C++/C++11 静态代码分析工具
- 线程安全的的map-CSuperMap
- 《C++编程规范:101条规则、准则与最佳实践》学习笔记
- vs2012编译c语言-指针不能判NULL
- 迷宫最少步数的求解(利用队列)
- 《C++必知必会》学习笔记
- C++笔记(8) template partitial specialization模板偏特化
- c++实现封装socket2