作业学习过程中,咱们可能需求去阅览不同类型的 Native 体系服务,也有可能会自己去完结一个 Native 体系服务。不管哪种情况都需求咱们了解基本的 Native 怎么去增加。就像咱们写 Android App 得先了解一下四大组件才行。接着咱们就来看看怎么增加一个 Android Native 体系服务。运用的源码版本是 AOSP android_r41。

文章配套源码:github.com/yuandaimaah…

开机自发动 Native 程序

首先,咱们先来完结一个敞开自动动的 Native 程序:

首先咱们在咱们的自定义 Product device/jelly/rice14 下创建如下的文件与文件夹:

关于自定义 Product,请检查 yuandaimaahao.github.io/AndroidFram… 02.%E7%8E%A9%E8%BD%ACAOSP%E7%AF%87/003.%20%E6%B7%BB%E5%8A%A0%20Product.html

HelloNativeService/
├── Android.bp
├── HelloServer.cpp
└── HelloServer.rc

其间 HelloServer.cpp:

#define LOG_TAG "helloserver"
#include <log/log.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
    ALOGD("Hello Server is runing");
    while(1) 
    {
        sleep(1);
    }
    return 0;
}

这是咱们的主程序,打印一个 Log,然后进入无线循环。

init.rc 脚本 HelloServer.rc:

service HelloServer /system/bin/HelloServer
    class core
    user system
    group system

当发动发动的时分,init 程序会解析咱们的 init.rc 教程,并发动咱们的程序。

接着,咱们需求编写咱们的 Android.bp 文件:

cc_binary {
    name: "HelloServer",
    srcs: ["HelloServer.cpp"],
    shared_libs: [
        "liblog",
    ],
    init_rc: ["HelloServer.rc"],
}

接着,改编译文件 rice14.mk :

PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST +=\
    /system/bin/HelloClient
PRODUCT_PACKAGES += \
    HelloServer

最终咱们,编译运转咱们的程序:

source build/envsetup.sh
lunch rice14-eng
make -j32
# 进入 Android 模拟器
adb shell 
logcat | grep Hello

接着咱们就能够看到打印的 Log 了:

07-16 16:25:06.670  1530  1530 D helloserver: Hello Server is runing

说明,咱们的开机自发动程序就发动成功了

增加 Native 服务

接着咱们在 device/jelly/rice14/HelloNativeService 目录下创建包目录 com/yuandaima

接着在包目录下创建:

package com.yuandaima;
interface IHello {
    void hello();
    int sum(int x, int y);
}

接着在项目目录下履行下面的命令,出产源文件:

aidl-cpp com/yuandaima/IHello.aidl ./ ./IHello.cpp

接着咱们完善 HelloServer 程序

#define LOG_TAG "helloserver"
#include <log/log.h>
#include <unistd.h>
#include <stdlib.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "com/yuandaima/IHello.h"
#include "com/yuandaima/BnHello.h"
using namespace android;
class MyHelloService : public com::yuandaima::BnHello
{
    public:
    binder::Status hello() 
    {
        ALOGI("server hello function is running");
        return binder::Status();
    }
    binder::Status sum(int32_t x, int32_t y, int32_t* _aidl_return) 
    {
         ALOGI("server sum function is running");
         *_aidl_return = x + y;
         return binder::Status();
    }
};
int main(int argc, char const *argv[])
{
    ALOGD("Hello Server is runing");
    defaultServiceManager()->addService(String16("MyHelloService"), new MyHelloService());
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

接着咱们写一个 HelloClient 来测验咱们的服务程序:

#define LOG_TAG "aidl_cpp"
#include <log/log.h>
#include <stdlib.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <binder/TextOutput.h>
#include <binder/IInterface.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "com/yuandaima/IHello.h"
#include "com/yuandaima/BpHello.h"
using namespace android;
int main(int argc, char const *argv[])
{
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("MyHelloService"));
    sp<com::yuandaima::IHello> hello = interface_cast<com::yuandaima::IHello>(binder);
    hello->hello();
    int ret = 0;
    hello->sum(1, 2, &ret);
    return 0;
}

然后,完善 Android.bp

cc_binary {
    name: "HelloServer",
    srcs: ["HelloServer.cpp", "IHello.cpp"],
    shared_libs: [
        "liblog",
        "libcutils",
        "libutils",
        "libbinder",
    ],
    init_rc: ["HelloServer.rc"],
}
cc_binary {
    name: "HelloClient",
    srcs: ["HelloClient.cpp", "IHello.cpp"],
    shared_libs: [
        "liblog",
        "libcutils",
        "libutils",
        "libbinder",
    ],
}

Selinux 配备

咱们需求修正体系的 sepolicy 文件,不能在自定义 Product 的 sepolicy 中增加 selinux 配备,由于会被体系的 seplicy 给覆盖掉。

system/sepolicy/privatesystem/sepolicy/prebuilts/api/29.0/private 中增加:

helloserver.te:

type helloserver_dt, domain, coredomain;
type helloserver_dt_exec, exec_type, file_type, system_file_type;
init_daemon_domain(helloserver_dt)
allow helloserver_dt servicemanager:binder { call transfer };
allow helloserver_dt HelloServer_service:service_manager { add find };
binder_use(helloserver_dt)
add_service(helloserver_dt,HelloServer_service)

编译时,编译体系会一起检查这两个目录,假如不同就会报错,所以咱们要一起修正两个地方。

system/sepolicy/private/file_contextssystem/sepolicy/prebuilts/api/29.0/private/file_contexts 中增加:

/system/bin/HelloServer     u:object_r:helloserver_dt_exec:s0

留意 file_contexts 最终一行有必要是空行,否则无法编译过。

system/sepolicy/private/service_contextssystem/sepolicy/prebuilts/api/29.0/private/service_contexts 中倒数第二行增加

MyHelloService                            u:object_r:HelloServer_service:s0

留意 service_contexts 最终一行有必要是空行,否则无法编译过。

system/sepolicy/private/service.te system/sepolicy/prebuilts/api/29.0/private/service.te 最终一样中增加:

type HelloServer_service,           service_manager_type;

最终编译发动模拟器:

source build/envsetup.sh
lunch rice14-eng
make -j32
# 进入 Android 模拟器
adb shell 
logcat | grep hello

然后就能够看到 Log 了:

07-16 16:42:11.616  1534  1534 D helloserver: Hello Server is runing

接着咱们运转咱们的客户端程序,再检查 Log:

logcat | grep "hello"
07-16 16:57:46.794  1531  1531 D helloserver: Hello Server is runing
07-16 16:58:52.638  1531  1577 I helloserver: server hello function is running
07-16 16:58:52.638  1531  1577 I helloserver: server sum function is running

这样,咱们的长途调用就成功了。

最终给同学们留一个问题,HelloClient 为什么没有配 Selinux 权限也能履行,假如要配备,应该怎么配备?

关于

我叫阿豪,2015 年本科毕业于国防科学技术大学指挥信息体系专业,毕业后从事信息化配备的研发作业,主要研讨方向是 Android Framework 与 Linux Kernel。

假如你对 Android Framework 感兴趣或许正在学习 Android Framework,能够重视我的微信公众号,我会持续共享我的学习经验,帮助正在学习的你少走一些弯路。学习过程中假如你有疑问或许你的经验想要共享给我们能够增加我的微信,我拉你进技术交流群。

假如你想体系学习 Anroid Framework 也能够重视我的抖音账号,在主页店肆即可购买付费课程

手把手教你添加 Android Native 系统服务