zoukankan      html  css  js  c++  java
  • 添加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
    ", "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


  • 相关阅读:
    科学计算——笔记
    Python_scrapyRedis零散
    Python博文_爬虫工程师是干什么的
    [单选题]怎样打开或创建一个文件?
    [问答题] 写出一个正则表达式,过虑网页上的所有JS/VBS脚本(即把script标记及其内容都去掉):
    [单选题]<?php$age =18;$age?$age+10:$age+20;echo $age;?>
    [单选题]有关PHP面向对象的说法,不对的是:
    [单选题]要循环操作非顺序索引的数组时,可以用下面哪个函数来读取数组当面元素的索引值?
    [单选题]PHP中定义常量的方法是:
    [单选题]stdClass的一个对象如何设置成员value的值?
  • 原文地址:https://www.cnblogs.com/yldf/p/6249870.html
Copyright © 2011-2022 走看看