-
Native Service 其实就是一个 linux 守护进程,提供一些服务,不过由于 android 的进程间通讯使用了 Binder 机制,那么我们就需要按照 android 的规则来实现我们的 Native Service。
-
客户端在请求 service 的服务时使用了一个具有相同接口的 Proxy 类。native service 这具体实现这个接口,所以 android 提供了 IInterface 类,其是”base class for Binder interfaces”,所以我们的 IZxTask 类继承它:
class IZxTask : public IInterface { public: enum { TASK_GET_PID = IBinder::FIRST_CALL_TRANSACTION, }; virtual int getPid() = 0; DECLARE_META_INTERFACE(ZxTask); };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
IMPLEMENT_META_INTERFACE(ZxTask, "android.hardware.IZxTask");
- 1
必须以 I 开头,因为后面会用到一些宏,比如 DECLARE_META_INTERFACE,I 开头是写到宏里面的,所以我们只要传入了 ZxTask 就行了。我们的 Native Service 提供一个接口就是返回 Service 的进程号。
下面我们就需要开始分化实现,一个是客户端,一个是 native service。
先来看代理类class BpZxTask : public BpInterface<IZxTask> { public: BpZxTask(const sp<IBinder>& binder) : BpInterface<IZxTask>(binder) { } virtual int getPid() { Parcel data, reply; data.writeInterfaceToken(IZxTask::getInterfaceDescriptor()); remote()->transact(TASK_GET_PID, data, &reply); return reply.readInt32(); } };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
BpInterface 模板类,其中的 p 就是代理的意思。其以我们前面定义的 Interface 为模板参数。
BpInterface 声明如下:template<typename INTERFACE> class BpInterface : public INTERFACE, public BpRefBase { public: BpInterface(const sp<IBinder>& remote); protected: virtual IBinder* onAsBinder(); };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
我们的 BpZxTask 需要实现我们定义的接口类中的接口函数。在实现中,我们是客户端,我们需要向 native service 提申请,我们使用 remote 获得关联 service 的 IBinder 对象,然后通过 transact 提交,通过 reply 获得返回值。
下面来看 BnInterface 的实现。
class BnZxTask : public BnInterface<IZxTask> { public: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); };
- 1
- 2
- 3
- 4
- 5
status_t BnZxTask::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case TASK_GET_PID: { CHECK_INTERFACE(IZxTask, data, reply); int32_t pid = getPid(); reply->writeInt32(pid); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
我们在 bpinterface 的 transact 调用会回调 bninterface 的 onTransact 来处理,我们根据 code 参数来进行请求的区分。
BnInterface 类模板其声明如下:
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(); };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
其一个父类是继承自 IInterface 的接口类,一个是代表 Binder service 服务端的 BBinder 类。
下面来实现 native service。
class ZxTaskService : public BinderService<ZxTaskService>, public BnZxTask { public: virtual int getPid(); static char const* getServiceName() { return "ZxTask"; } friend class BinderService<ZxTaskService>; }; int ZxTaskService::getPid() { return getpid(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
我们在此实现服务提供的 getPid 接口就 ok,BinderService 模板为我们启动一个 Service 实现了逻辑封装。
BinderService 实现如下:template<typename SERVICE> class BinderService { public: static status_t publish(bool allowIsolated = false) { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService( String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); } static void publishAndJoinThreadPool(bool allowIsolated = false) { publish(allowIsolated); joinThreadPool(); } static void instantiate() { publish(); } static status_t shutdown() { return NO_ERROR; } private: static void joinThreadPool() { sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); IPCThreadState::self()->joinThreadPool(); } };
- 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
其要求模板参数实现
getServiceName
方法,publish
和publishAndJoinThreadPool
函数实现了该 service 添加到 SM 的逻辑,publish 只是 add,而publishAndJoinThreadPool
会启动该 service。这里我们就完成了 native service 的开发,我们将其编成库。
Android.mkLOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ ZxTask.cpp \ ZxTaskService.cpp LOCAL_C_INCLUDES := \ system/core/include \ frameworks/native/include LOCAL_SHARED_LIBRARIES := \ libbinder \ libutils \ LOCAL_MODULE:= libzxtask include $(BUILD_SHARED_LIBRARY)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
我们写一个 service 的可执行程序。
main.cpp#include "service/ZxTaskService.h" int main() { /* code */ android::ZxTaskService::publishAndJoinThreadPool(); return 0; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Android.mk
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ main.cpp \ LOCAL_C_INCLUDES := frameworks/base/zxTask LOCAL_MODULE:= zxtaskservice LOCAL_SHARED_LIBRARIES := libzxtask libutils libbinder include $(BUILD_EXECUTABLE)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
写一个测试客户端
main.cpp
#include "service/ZxTask.h" #include <binder/IServiceManager.h> #include <unistd.h> #include <stdio.h> int main() { using namespace android; sp<IServiceManager> sm =defaultServiceManager(); printf("%s\n", "get serviceManager"); sp<IBinder> binder =sm->getService(String16("ZxTask")); sp<IZxTask> mTask =interface_cast<IZxTask>(binder); printf("ZxTask Service pid %d, client pid:%d",mTask->getPid(), getpid()); return 0; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
Android.mk
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ main.cpp \ LOCAL_C_INCLUDES := frameworks/base/zxTask LOCAL_MODULE:= zxtaskclient LOCAL_SHARED_LIBRARIES := libzxtask libutils libbinder include $(BUILD_EXECUTABLE)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
其中用到了
interface_cast
。template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }
- 1
- 2
- 3
- 4
- 5
其使用了 asInterface 函数,而这个函数就是我们在 IZxTask 里面使用
DECLARE_META_INTERFACE
声明的。#define DECLARE_META_INTERFACE(INTERFACE) \ static const android::String16 descriptor; \ static android::sp<I##INTERFACE> asInterface( \ const android::sp<android::IBinder>& obj); \ virtual const android::String16& getInterfaceDescriptor() const;\ I##INTERFACE(); \ virtual ~I##INTERFACE();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
其声明了一个描述的类属性,我们使用的
asInterface
函数。
看下IMPLEMENT_META_INTERFACE
宏。#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ const android::String16 I##INTERFACE::descriptor(NAME); \ const android::String16& \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ } \ android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ I##INTERFACE::I##INTERFACE() { } \ I##INTERFACE::~I##INTERFACE() { } \
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
主要看
asInterface
的实现。其会调用 IBinder 的 queryLocalInterface 查询我们的接口对象,这里使用了基类指针,如果没有就 new 出来。我们的 BpZxTask 只有在这个函数中使用,这也是为什么我在实现时,指示全部把它放在了 cpp 文件中。intr = new Bp##INTERFACE(obj);
- 1
这一句表明我们的 Proxy 类一定以 Bp 开头且 IBinder 对象作为构造的参数传入,实现了 proxy 和 IBinder 对象的绑定。
sp<IBinder> binder =sm->getService(String16("ZxTask"));
- 1
根据 service 名获得这个 service 的 IBinder 对象,使用
interface_cast
实现了客户端的 Proxy 和 service 的 IBinder 的绑定,然后我们在 getPid 中就可以调用 IBinder 的 transact 函数,这样就和 remote 通讯上,回调到 native service 的 onTransact 的接口,然后处理了将结果返回,这样就实现了 client 和 service 的通讯。运行如下图:
转载于:https://www.cnblogs.com/yldf/p/6249870.html