Android添加一个Native Service



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);
};
IMPLEMENT_META_INTERFACE(ZxTask, "android.hardware.IZxTask");

必须以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();
    }
};

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

BpInterface声明如下:

template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
                                BpInterface(const sp<IBinder>& remote);

protected:
    virtual IBinder*            onAsBinder();
};

我们的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);
};
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);
    }
}

我们在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();
};

其一个父类是继承自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();
}

我们在此实现服务提供的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();
    }
};

其要求模板参数实现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)

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

main.cpp

#include "service/ZxTaskService.h"

int main()
{
    /* code */
    android::ZxTaskService::publishAndJoinThreadPool();
    return 0;
}

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)

写一个测试客户端

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;
}

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)

其中用到了interface_cast

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

其使用了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();

其声明了一个描述的类属性,我们使用的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() { }                          \

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

intr = new Bp##INTERFACE(obj); 

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

  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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-27 11:00:44

Android添加一个Native Service的相关文章

为Android添加一个开机完成后执行的脚本

1.编写相应的执行脚本文件ledgpio.sh,将其放在device/rockchip/rk3399路径下:#!/system/bin/shinsmod /system/lib/modules/ledgpio.ko 2.修改device.mk文件,添加以下内容:#ledgpioPRODUCT_COPY_FILES += \ device/rockchip/rk3399/ledgpio.sh:system/bin/ledgpio.sh 3.在init.rk30board.rc中创建服务:servi

Android 添加framework资源包

为Android系统添加一个新的资源包 概述 传统的Android系统只有一个framework-res.apk资源包,第三方厂商在进行rom定制时会直接修改framework res资源,达到适配目的.但是这种方式跟原生资源的耦合度过高,在系统迁移或者framework ui移植时需要进行人工merge,工作量巨大.通过为Android添加一个新的独立的资源包,可以将厂商定制资源独立出来,可移植.可维护性非常好. 实现 具体做法可以分为以下几个步骤: 1)修改build/core/clear_

Android 6.0一个完整的native service

 上一篇博客<Android 6.0 如何添加完整的系统服务(app-framework-kernel)>http://www.cnblogs.com/hackfun/p/7418902.html介绍了如何添加一个系统服务,客户端和服务端都是基于JAVA实现的OpersysService.经过进一步的学习,我将演示如何使用C++实现一个相同功能的系统服务hfnativeservice.为了兼容OpersysService,将保留Opersys-Service服务端中的HAL和driver,供h

Android软硬整合设计与框架揭秘: HAL&amp;Framework &amp;Native Service &amp;App&amp;HTML5架构设计与实战开发

掌握Android从底层开发到框架整合技术到上层App开发及HTML5的全部技术: 一次彻底的Android架构.思想和实战技术的洗礼: 彻底掌握Andorid HAL.Android Runtime.Android Framework.Android Native Service.Android Binder.Android App.Android Testing.HTML5技术的源泉和精髓等核心技术,不仅仅是技术和代码本身,更重要的是背后的设计思想和商业哲学. 一.课程特色 l  贯通And

Android软硬整合设计与框架揭秘: HAL&amp;Framework &amp;Native Service &amp;App&amp;Browser架构设计与实战开发

在软硬整合领域, Android以其对软件和硬件的高度开放性引领了当今的软硬整合潮流,全世界正在进行一场轰轰烈烈的Android运动,Android以不可思议的速度渗透越来越广的领域,Android智能手机.Android智能电视.Android微波炉.Android平板电脑.Android智能机器人.Android车载系统等越来越多的Android产品涌入人们的工作和生活中,自从Google的[email protected]战略发布以来,更是让世界对Android充满了怦然心动的期待,可以预

在Android应用中添加React Native支持

用android studio创建一个基本的android hello world程序 在项目根目录中通过npm向导生成package.json文件,在cmd中输入命令:npm init 在package.json文件中添加启动脚本"start": "node node_modules/react-native/local-cli/cli.js start" 添加react-native npm依赖,在命令行输入npm install react react-nat

如何写一个native层的service

android的service大概有这么几种形式,Java service ,native service,或者Java层通过某种通信方式比如socket和demon交互. Java层的aidl很方便,写socket的demon方式也很好理解,native的就显得稍微麻烦一点,咱们通过一个例子来说一下,首先说我们不讲解binder的内部机制-. 我们打算写个简单的service,只提供set和get方法 1. 先写一个bin 的可执行文件 int main(int argc, char** ar

Android架构设计和软硬整合完整训练:HAL&amp;Framework&amp;Native Service&amp;Android Service&amp;Best Practice

如何理解Android架构设计的初心并开发出搭载Android系统并且具备深度定制和软硬整合能力特色产品,是本课程解决的问题. 课程以Android的五大核心:HAL.Binder.Native Service.Android Service(并以AMS和WMS为例).View System为主轴,一次性彻底掌握Android的精髓. 之所以是开发Android产品的必修课,缘起于: 1, HAL是Android Framework&Application与底层硬件整合的关键技术和必修技术: 2

Android架构设计和软硬整合:HAL&amp;Framework&amp;Native Service&amp;Android Service&amp;Best Practice

如何理解Android架构设计的初心并开发出搭载Android系统并且具备深度定制和软硬整合能力特色产品,是本课程解决的问题. 课程以Android的五大核心:HAL.Binder.Native Service.Android Service(并以AMS和WMS为例).View System为主轴,一次性彻底掌握Android的精髓. 之所以是开发Android产品的必修课,缘起于: 1, HAL是Android Framework&Application与底层硬件整合的关键技术和必修技术: 2