在Binder库中,Service组件和Client组件分别使用模板类BnInterface和BpInterface来描述,前者称为Binder本地对象,后者称为Binder代理对象。Binder库中的Binder本地对象和Binder代理对象分别对应于Binder驱动程序中的Binder实体对象和Binder引用对象。
下面将简要介绍Binder进程间的通信,代码包含Server进程和Client进程,Server进程实现了一个Service组件,负责管理前面介绍的虚拟硬件设备mydev的寄存器val,并且向Client进程提供访问服务。以下将实例划分为common、server和client三个模块,其中common实现了硬件访问服务接口IMydevService,以及Binder本地对象类BnMydevService和Binder代理对象类BpMydevService;server实现了一个Server进程,里面包含一个Service组件MydevService;client实现了一个Client进程,它通过一个BpMydevService代理对象去访问运行在Server进程中的Service组件MydevService所提供的服务。
程序目录结构
1 | ~/Android/external/binder |
Server进程
- common/IMydevService.h
1 |
|
- common/IMydevService.cpp
1 |
|
- server/MydevServer.cpp
1 |
|
- server/Android.mk
1
2
3
4
5
6
7
8LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := ../common/IMydevService.cpp \
MydevServer.cpp
LOCAL_SHARED_LIBRARIES := libcutils libutils libbinder
LOCAL_PACKAGE_NAME := MydevServer
include $(BUILD_EXECUTABLE)
Client进程
client/MydevClient.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
int main()
{
sp<IBinder> binder = defaultServiceManager()->getService(String16(MYDEV_SERVICE));
if (binder == NULL) {
LOGE("Failed to get mydev service: %s.\n", MYDEV_SERVICE);
return -1;
}
sp<IMydevService> service = IMydevService::asInterface(binder);
if (service == NULL) {
LOGE("Failed to get mydev service interface.\n");
return -2;
}
printf("Read original value from MydevService:\n");
int32_t val = service->getVal();
printf(" %d.\n", val);//0
printf("Add value 1 to MydevService.\n");
val += 1;
service->setVal(val);
printf("Read the value from MydevService again:\n");
val = service->getVal();
printf(" %d.\n", val);//1
return 0;
}
- client/Android.mk
1
2
3
4
5
6
7
8LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := ../common/IMydevService.cpp \
MydevClient.cpp
LOCAL_SHARED_LIBRARIES := libcutils libutils libbinder
LOCAL_PACKAGE_NAME := MydevClient
include $(BUILD_EXECUTABLE)
单独编译server和client
- ~/Android$ mmm ./external/binder/server/
- ~/Android$ mmm ./external/binder/client/
编译完成之后,就可以在out/target/product/generic/system/bin目录下看到编译结果的输出文件MydevServer和MydevClient了
重新打包system.img文件
- ~/Android$make snod
运行模拟器:
- ~/Android$emulator -kernel kernel/goldfish/arch/arm/boot/zImage &
- ~/Android$ adb shell
- root@android:/ # cd system/bin
- root@android:/system/bin # ./MydevServer &
- root@android:/system/bin # ./MydevXClient
1
2
3
4
5Read original value from MydevService:
0.
Add value 1 to MydevService.
Read the value from MydevService again:
1.