本小结描述native层进程间binder通信,包括client端和 Server端. 下面将根据一个具体的事例来介绍如何在native层使用binder. 自顶往下看,首先看到的就是Android.mk, 可以看到在使用binder之前,依赖系统的动态库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder
LOCAL_MODULE := TestServer
LOCAL_SRC_FILES := \
ITestService.cpp \
TestServer.cpp
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder
LOCAL_MODULE := TestClient
LOCAL_SRC_FILES := \
ITestService.cpp \
TestClient.cpp
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
首先看一下测试例子得文件结构构成:
Test.h:定义interface的接口引用类,传输过程的枚举,client端的引用类.
ITestService.cpp: 实现引用类方法.
TestClient.cpp: 申明实现binder引用类.
TestServer.cpp: 申明实现binder实体类,往service manager里注册binder服务.
- 申明service的接口ITestService(Test.h)
-
class ITestService : public IInterface { public: DECLARE_META_INTERFACE(TestService); // declare macro virtual void test()=0; };
使用DECLARE_META_INTERFACE,主要做了一些函数的申明但并没有定义,主要的接口为:descriptor, asInterface, getInterfaceDescriptor接口。
- 为ITestService接口的所有方法声明枚举,一个枚举对应ITestService里的一个方法(Test.h), 相当于ITestService里的test方法。
enum
{
TEST = IBinder::FIRST_CALL_TRANSACTION,
};
- 申明binder引用类BpTestService(Test.h), 这个类一般是在client端使用的。
class BpTestService: public BpInterface<ITestService> {
public:
BpTestService(const sp<IBinder>& impl);
virtual void test();
};
- 实现ITestService接口的方法(ITestService.cpp)
前面的DECLARE_META_INTERFACE,只是声明了接口的方法并没有实现,这里的代码实现了这些方法。
IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService");
- 实现binder引用类的BpTestService(TestClient.cpp)
#include "Test.h"
namespace android {
BpTestService::BpTestService(const sp<IBinder>& impl) :
BpInterface<ITestService>(impl) {
}
void BpTestService::test() {
printf("in the get Test\n");
Parcel data, reply;
data.writeInterfaceToken(ITestService::getInterfaceDescriptor());
remote()->transact(TEST, data, &reply);
printf("send Print %d\n", reply.readInt32());
}
}
int main() {
sp < IServiceManager > sm = defaultServiceManager();
sp < IBinder > binder = sm->getService(String16("service.testservice"));
sp<ITestService> cs = interface_cast < ITestService > (binder);
cs->test();
return 0;
}
Service client端通过service manager拿到binder的一个引用,也就是BpTestService. 它也会实现test方法,最终会通过跨进程调用binder实体对象BnInterface的test方法。在我们的实例中,只是要调用BpInterface的构造器,实现ITestService接口的test方法,client端实现test方法,通过 remote的transact 方法就能把数据交至server端,server的返回结果放在reply里。
- 实现binder实体类的BnTestService(TestServer.cpp)
BnInterface是binder的核心库和框架中的类,表示binder的实体类,在onTransact中会根据client端传来的命令(正如上文的enum TEST)调用不用不同的函数。
#include "Test.h"
namespace android {
class BnTestService: public BnInterface<ITestService> {
public:
virtual status_t;
onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags = 0);
virtual void test() {
printf("Now get test\n");
}
};
status_t BnTestService::onTransact(uint_t code, const Parcel& data,
Parcel* reply, uint32_t flags) {
switch (code) {
case TEST: {
printf("got the client msg\n");
CHECK_INTERFACE(ITest, data, reply);
test();
reply->writeInt32(100);
return NO_ERROR;
}
break;
default:
break;
}
return NO_ERROR;
}
}
int main() {
sp < ProcessState > proc(ProcessState::self());
sp < IServiceManager > sm = defaultServiceManager();
sm->addService(String16("service.testservice"), new BnTestService());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool(); //等待线程结束
return 0;
}
- 结果验证
adb push TestService TestClient /system/bin
cd /system/bin
./TestService
./TestClient