添加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

posted @ 2016-08-25 18:22  岳麓丹枫  阅读(118)  评论(0编辑  收藏  举报