binder-使用C++编写binder系统

前面的文章中我们编写过了C语言的binder程序,由于android它自己的服务用的都是cpp,因此我们需要用cpp来编写一次,当然你可以选择不写,写这些代码主要是让大家对cpp部分的代码,以及一些就结构体能够有一些了解,在后续的分析中会轻松许多

编写过程中会出现很多奇奇怪怪的类名,不要慌,后续会详细讲解他们的作用

我们以打开手电筒和关闭手电筒为例

  • 定义XXX接口
  • 定义BnXXX和BpXXX(Bp是代理类,Bn是服务端处理代码)
  • BnXXX 有 onTransact 方法
  • server端实现 BnXXX
  • client端实现 BpXXX

头文件我们可以参考 IMediaPlayerService.h

编写头文件 IFlashLightService.h ,头文件包含两个方法,打开手电筒和关闭手电筒

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef ANDROID_ILIGHTSERVICE_H
#define ANDROID_ILIGHTSERVICE_H

#include <utils/Errors.h> // for status_t
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <system/audio.h>

namespace android{
class IFlashLightService:public IInterface{
public:
//有 DECLARE 声明就会有 IMPLEMENT 实现,两者对应,这是一个宏
//注意这个宏,基类中的一些实现都是通过这个宏来做的
DECLARE_META_INTERFACE(FlashLightService);
virtual void close(void) = 0 ;
virtual void open(char *name) = 0 ;
};
class BnFlashLightService: public BnInterface<IFlashLightService>{
public:
virtual status_t onTransact( int32_t code, const Parcel& data,Parcel* reply,uint32_t flags = 0);
};
};

#endif

IFlashLightService.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <IFlashLightService.h>

namespace android{

enum {
LIGHT_OPEN,
LIGHT_CLOSE
};

class BpFlashLightService: public BpInterface<IFlashLightService>
{
public:
BpFlashLightService(const sp<IBinder>& impl)
: BpInterface<IFlashLightService>(impl)
{
}
virtual void close(void){
Parcel data, reply;
remote()->transact(LIGHT_CLOSE, data, &reply);
};
virtual int open(char *name){
Parcel data, reply;
data.writeString16(String16(name));
remote()->transact(LIGHT_OPEN, data, &reply);
return reply.readInt32();
}
}

IMPLEMENT_META_INTERFACE(FlashLightService, "android.media.IFlashLightService");//IMPLEMENT宏

status_t BnFlashLightService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case LIGHT_OPEN: {
close();
} break;
case LIGHT_CLOSE: {
const char* name = data.readCString();
int ret = open(name);
reply->writeInt32(ret);
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}

void BnFlashLightService::close(){

}
void BnFlashLightService::open(char *name){

}
};

注意 class BpFlashLightService: public BpInterface

BpInterface是一个模板类

1
2
3
4
5
6
7
8
9
10
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();
};

所以 BpFlashLightService 继承两个类,BpInterface和 IFlashLightService,因此在 BpFlashLightService 它是可以使用 IFlashLightService 实现类的方法的

IFlashLightService 的实现由两个,一个BpFlashLightService,一个 BnFlashLightService

接下来我们编写测试代码,client和server

server:

参考 main_mediaserver.cpp

在之前编写C语言的binder系统时,一个server_test的流程就是添加服务以及循环处理服务的过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>

using namespace android;

int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);

//打开驱动 mmap 等等
sp<ProcessState> proc(ProcessState::self());
//获取BpServierManager 可以通过他来调用addService
sp<IServiceManager> sm(defaultServiceManager());

sm->addService(String16("hello"),new BnFlashLightService());

//循环体
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}

client:

我们还是参考源代码是如何获取服务的

通过androidxref网站的搜索,搜索 sm->getService ,可以找到一些类似的代码

找到一个 rsa_meth.cpp

1
2
3
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>

using namespace android;

int main(int argc __unused, char **argv)
{
//打开驱动 mmap 等等
sp<ProcessState> proc(ProcessState::self());
//获取BpServierManager 可以通过他来调用addService
sp<IServiceManager> sm(defaultServiceManager());

sp<IBinder> binder = sm->getService(String16("android.media.flashLight"));
//根据binder节点来转换成一个Service类
sp<IFlashLightService> service = interface_cast<IFlashLightService>(binder);
service->close();
service->open(argv[2]);
}

在编写过程中,希望读者能够多在源码中畅游,多多了解这些类的继承关系,以及它们都有写什么成员,对后续的理解也会有帮助

在C部分的分析中,我们是根据服务的注册以及使用过程来走流程,在cpp的部分,我们同样也是通过这两个部分来分析源码,下篇文章会开始分析cpp的机制