添加native service

原文地址:http://blog.csdn.net/zhx6044/article/details/47342227

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方法,publishpublishAndJoinThreadPool函数实现了该 service 添加到 SM 的逻辑,publish 只是 add,而publishAndJoinThreadPool会启动该 service。

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

LOCAL_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://git.oschina.net/zhouX/servicedemo.git


转载于:https://www.cnblogs.com/yldf/p/6249870.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值