[关闭]
@XiangZhou 2015-08-07T16:36:12.000000Z 字数 6024 阅读 6452

Android添加一个Native Service

android native_service


Native Service其实就是一个linux守护进程,提供一些服务,不过由于android的进程间通讯使用了Binder机制,那么我们就需要按照android的规则来实现我们的Native Service。

客户端在请求service的服务时使用了一个具有相同接口的Proxy类。native service这具体实现这个接口,所以android提供了IInterface类,其是"base class for Binder interfaces",所以我们的IZxTask类继承它:

  1. class IZxTask : public IInterface {
  2. public:
  3. enum { TASK_GET_PID = IBinder::FIRST_CALL_TRANSACTION,
  4. };
  5. virtual int getPid() = 0;
  6. DECLARE_META_INTERFACE(ZxTask);
  7. };
  1. IMPLEMENT_META_INTERFACE(ZxTask, "android.hardware.IZxTask");

必须以I开头,因为后面会用到一些宏,比如DECLARE_META_INTERFACE,I开头是写到宏里面的,所以我们只要传入了ZxTask就行了。我们的Native Service提供一个接口就是返回Service的进程号。
下面我们就需要开始分化实现,一个是客户端,一个是native service。
先来看代理类

  1. class BpZxTask : public BpInterface<IZxTask> {
  2. public:
  3. BpZxTask(const sp<IBinder>& binder)
  4. : BpInterface<IZxTask>(binder)
  5. {
  6. }
  7. virtual int getPid()
  8. {
  9. Parcel data, reply;
  10. data.writeInterfaceToken(IZxTask::getInterfaceDescriptor());
  11. remote()->transact(TASK_GET_PID, data, &reply);
  12. return reply.readInt32();
  13. }
  14. };

BpInterface模板类,其中的p就是代理的意思。其以我们前面定义的Interface为模板参数。
BpInterface声明如下:

  1. template<typename INTERFACE>
  2. class BpInterface : public INTERFACE, public BpRefBase
  3. {
  4. public:
  5. BpInterface(const sp<IBinder>& remote);
  6. protected:
  7. virtual IBinder* onAsBinder();
  8. };

我们的BpZxTask需要实现我们定义的接口类中的接口函数。在实现中,我们是客户端,我们需要向native service提申请,我们使用remote获得关联service的IBinder对象,然后通过transact提交,通过reply获得返回值。

下面来看BnInterface的实现。

  1. class BnZxTask : public BnInterface<IZxTask> {
  2. public:
  3. virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
  4. };
  1. status_t BnZxTask::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  2. {
  3. switch (code) {
  4. case TASK_GET_PID: {
  5. CHECK_INTERFACE(IZxTask, data, reply);
  6. int32_t pid = getPid();
  7. reply->writeInt32(pid);
  8. return NO_ERROR;
  9. } break;
  10. default:
  11. return BBinder::onTransact(code, data, reply, flags);
  12. }
  13. }

我们在bpinterface的transact调用会回调bninterface的onTransact来处理,我们根据code参数来进行请求的区分。

BnInterface类模板其声明如下:

  1. template<typename INTERFACE>
  2. class BnInterface : public INTERFACE, public BBinder
  3. {
  4. public:
  5. virtual sp<IInterface>
  6. queryLocalInterface(const String16& _descriptor);
  7. virtual const String16& getInterfaceDescriptor() const;
  8. protected:
  9. virtual IBinder* onAsBinder();
  10. };

其一个父类是继承自IInterface的接口类,一个是代表Binder service服务端的BBinder类。

下面来实现native service。

  1. class ZxTaskService : public BinderService<ZxTaskService>, public BnZxTask {
  2. public:
  3. virtual int getPid();
  4. static char const* getServiceName() { return "ZxTask"; }
  5. friend class BinderService<ZxTaskService>;
  6. };
  7. int ZxTaskService::getPid()
  8. {
  9. return getpid();
  10. }

我们在此实现服务提供的getPid接口就ok,BinderService模板为我们启动一个Service实现了逻辑封装。
BinderService实现如下:

  1. template<typename SERVICE>
  2. class BinderService
  3. {
  4. public:
  5. static status_t publish(bool allowIsolated = false) {
  6. sp<IServiceManager> sm(defaultServiceManager());
  7. return sm->addService(
  8. String16(SERVICE::getServiceName()),
  9. new SERVICE(), allowIsolated);
  10. }
  11. static void publishAndJoinThreadPool(bool allowIsolated = false) {
  12. publish(allowIsolated);
  13. joinThreadPool();
  14. }
  15. static void instantiate() { publish(); }
  16. static status_t shutdown() { return NO_ERROR; }
  17. private:
  18. static void joinThreadPool() {
  19. sp<ProcessState> ps(ProcessState::self());
  20. ps->startThreadPool();
  21. ps->giveThreadPoolName();
  22. IPCThreadState::self()->joinThreadPool();
  23. }
  24. };

其要求模板参数实现getServiceName方法,publishpublishAndJoinThreadPool函数实现了该service添加到SM的逻辑,publish只是add,而publishAndJoinThreadPool会启动该service。

这里我们就完成了native service的开发,我们将其编成库。
Android.mk

  1. LOCAL_PATH:= $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_SRC_FILES := \
  4. ZxTask.cpp \
  5. ZxTaskService.cpp
  6. LOCAL_C_INCLUDES := \
  7. system/core/include \
  8. frameworks/native/include
  9. LOCAL_SHARED_LIBRARIES := \
  10. libbinder \
  11. libutils \
  12. LOCAL_MODULE:= libzxtask
  13. include $(BUILD_SHARED_LIBRARY)

我们写一个service的可执行程序。
main.cpp

  1. #include "service/ZxTaskService.h"
  2. int main()
  3. {
  4. /* code */
  5. android::ZxTaskService::publishAndJoinThreadPool();
  6. return 0;
  7. }

Android.mk

  1. LOCAL_PATH:= $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_SRC_FILES := \
  4. main.cpp \
  5. LOCAL_C_INCLUDES := frameworks/base/zxTask
  6. LOCAL_MODULE:= zxtaskservice
  7. LOCAL_SHARED_LIBRARIES := libzxtask libutils libbinder
  8. include $(BUILD_EXECUTABLE)

写一个测试客户端

main.cpp

  1. #include "service/ZxTask.h"
  2. #include <binder/IServiceManager.h>
  3. #include <unistd.h>
  4. #include <stdio.h>
  5. int main()
  6. {
  7. using namespace android;
  8. sp<IServiceManager> sm =defaultServiceManager();
  9. printf("%s\n", "get serviceManager");
  10. sp<IBinder> binder =sm->getService(String16("ZxTask"));
  11. sp<IZxTask> mTask =interface_cast<IZxTask>(binder);
  12. printf("ZxTask Service pid %d, client pid:%d",mTask->getPid(), getpid());
  13. return 0;
  14. }

Android.mk

  1. LOCAL_PATH:= $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_SRC_FILES := \
  4. main.cpp \
  5. LOCAL_C_INCLUDES := frameworks/base/zxTask
  6. LOCAL_MODULE:= zxtaskclient
  7. LOCAL_SHARED_LIBRARIES := libzxtask libutils libbinder
  8. include $(BUILD_EXECUTABLE)

其中用到了interface_cast

  1. template<typename INTERFACE>
  2. inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
  3. {
  4. return INTERFACE::asInterface(obj);
  5. }

其使用了asInterface函数,而这个函数就是我们在IZxTask里面使用DECLARE_META_INTERFACE声明的。

  1. #define DECLARE_META_INTERFACE(INTERFACE) \
  2. static const android::String16 descriptor; \
  3. static android::sp<I##INTERFACE> asInterface( \
  4. const android::sp<android::IBinder>& obj); \
  5. virtual const android::String16& getInterfaceDescriptor() const;\
  6. I##INTERFACE(); \
  7. virtual ~I##INTERFACE();

其声明了一个描述的类属性,我们使用的asInterface函数。
看下IMPLEMENT_META_INTERFACE宏。

  1. #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
  2. const android::String16 I##INTERFACE::descriptor(NAME); \
  3. const android::String16& \
  4. I##INTERFACE::getInterfaceDescriptor() const { \
  5. return I##INTERFACE::descriptor; \
  6. } \
  7. android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
  8. const android::sp<android::IBinder>& obj) \
  9. { \
  10. android::sp<I##INTERFACE> intr; \
  11. if (obj != NULL) { \
  12. intr = static_cast<I##INTERFACE*>( \
  13. obj->queryLocalInterface( \
  14. I##INTERFACE::descriptor).get()); \
  15. if (intr == NULL) { \
  16. intr = new Bp##INTERFACE(obj); \
  17. } \
  18. } \
  19. return intr; \
  20. } \
  21. I##INTERFACE::I##INTERFACE() { } \
  22. I##INTERFACE::~I##INTERFACE() { } \

主要看asInterface的实现。其会调用IBinder的queryLocalInterface查询我们的接口对象,这里使用了基类指针,如果没有就new出来。我们的BpZxTask只有在这个函数中使用,这也是为什么我在实现时,指示全部把它放在了cpp文件中。

  1. intr = new Bp##INTERFACE(obj);

这一句表明我们的Proxy类一定以Bp开头且IBinder对象作为构造的参数传入,实现了proxy和IBinder对象的绑定。

  1. sp<IBinder> binder =sm->getService(String16("ZxTask"));

根据service名获得这个service的IBinder对象,使用interface_cast实现了客户端的Proxy和service的IBinder的绑定,然后我们在getPid中就可以调用IBinder的transact函数,这样就和remote通讯上,回调到native service的onTransact的接口,然后处理了将结果返回,这样就实现了client和service的通讯。

运行如下图:

此处输入图片的描述

代码例子:https://git.oschina.net/zhouX/servicedemo.git

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注