Android 8.1 从零开始写 HAL -- (4) 编译与打包

Android 8.1 从零开始写 HAL – (4) 编译与打包

注意:本文基于 Android 8.1 进行分析
Qidi 2020.07.18 (Markdown & Haroopad)


【前言】

对于 demoComponent HAL,在上一篇文章《Android 8.1 从零开始写 HAL – (3) 实现 Bp、Bn 端》中,我们已经编写好了 demoService 代码、Bp 端代码和 Bn 端代码。现在来着手把源码编译成可执行文件和库,并且将它们打包进系统镜像中。


一、编写 Makefile

这里说的 Makefile 是指 Android.bp(当然也可以使用 Android.mk,语法稍有区别)

default/ 目录下新建文件 Android.bp,内容如下:

/*****************************************************************************
 * Copyright (C) 2020 Qidi.Huang
 *
 * Brief:
 *    Build demo service into an executable binary.
 *
 * Author: [email protected]
 *****************************************************************************/

cc_defaults {
    name: "demoSvc_v1_0_default",
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libutils",
        "libhardware",
        "libbinder",
        "[email protected]_vendor",
    ],
    cflags: [
        "-Wall",
        "-Wextra",
        "-Werror",
    ],
}

cc_binary {
    name: "[email protected]",
    defaults: ["demoSvc_v1_0_default"],
    init_rc: ["[email protected]"],
    vendor: true,
    relative_install_path: "hw",

    include_dirs:["vendor/harman/hardware/interfaces/demoComponent/demoService/1.0/default"],
    srcs: [
        "DemoService.cpp",
        "DemoServiceImpl.cpp",
        "BpDemoService.cpp",
        "BnDemoService.cpp"
    ],
    shared_libs: [
        "libbase",
        "libprotobuf-cpp-lite",
        "[email protected]_vendor"
    ],
}

目标 demoSvc_v1_0_default 可以理解成是将和 Binder 框架相关的库打包而成的一个总的库文件,[email protected]_vendor 是通过接口描述文件自动生成的,同样可以在 /out/soong/.intermediates/... 目录下找到;

目标 [email protected] 就是最终要生成的可执行文件;

属性 vendor: true 表示这是一个自定义的文件;

属性 relative_install_path: "hw" 和前一个属性共同作用,表示生成文件的相对存放位置在 out/target/product//vendor/bin/hw/ 目录;

属性 srcs 属性下包含了我们在之前几篇文章里编写的所有源文件 —— DemoService.cppDemoServiceImpl.cppBpDemoService.cppBnDemoService.cpp

如果不想过多关注,简单按照这个 Makefile 的格式,相应把各位置的文件名改成你自己的文件名也是可行的。


二、编写 HAL 启动脚本

基于上述的 Makefile 在 default/ 目录下**手动(mm 命令)**进行编译,我们能得到名为 [email protected] 的可执行文件。为了让 demoComponent HAL 随系统启动而启动,我们还需要编写 *.rc 脚本,并在脚本中标注进程名、可执行文件、用户组等信息。

一般以可执行文件名作为脚本名,也就是 [email protected]

default/ 目录下新建脚本,内容如下:

service MyDemoService /vendor/bin/hw/[email protected]
    class main
    user system
    group system
    capabilities sys_nice net_bind_service net_admin net_raw

关键字 service 用来定义一个进程(或称为本地服务),后面第一个参数 MyDemoService 是进程名,第二个参数是可执行文件的绝对路径;

class main 表示把 MyDemoService 归属到 main 类;

user systemgroup system 表示 MyDemoService 的用户和组用户都是 system;

capabilities 指定了一些权限相关的属性。


三、打包可执行文件到系统镜像

要实现 demoComponent HAL 随系统启动而启动,需要将它的 可执行文件*.rc 文件都打包进系统镜像。通过修改产品的 Makefile 可以实现这一目的。

先在 /device///common/ 路径下为 demoComponent HAL 新建一个名为 demoComponent/ 的专属目录,再在这个目录下创建名为 device_demoComponent.mk 的 Makefile。(其实叫什么名字都可以,但是用 demoComponent 更直观)

如此一来我们就有了 /device/harman/broxton/common/demoComponent/device_demoComponent.mk 除去注释,Makefile 内容只有一句话:

############################
# DemoService
############################

PRODUCT_PACKAGES += [email protected]

这句话表示要将可执行文件 [email protected] 打包进系统镜像,确切地说是打包进 vendor.img

切记,不要忘了把我们新建的 Makefile 添加到产品的 Makefile 中。 产品 Makefile 一般位于 /device////device.mk,所以我们在 /device/harman/broxton/XXXX/device.mk 中增加以下语句(以 diff 形式展示):

diff --git a/XXXX/device.mk b/XXXX/device.mk
index b0866f3d2..d7a7d8ef7 100755
--- a/XXXX/device.mk
+++ b/XXXX/device.mk
@@ -1,5 +1,6 @@
 include device/harman/broxton/common/device_common.mk
 include $(LOCAL_PATH)/audio/device_audio.mk
+include device/harman/broxton/common/demoComponent/device_demoComponent.mk
 include device/harman/broxton/common/tuner/device_radioTuner.mk
 include device/harman/broxton/common/speech/vpa.mk

注意上面以 + 开头的 include 语句,就是在引用我们的新建 Makefile。


【结语】

打包已经完成,我们的 demoComponent HAL 正跃跃欲试。但如果你将打包好的系统镜像烧写到设备上,会发现 demoComponent HAL 不能按照预期工作,甚至连自启动都做不到。相反,我们会在 logcatdmesg 里发现有很多日志提示我们没有操作权限。 下一篇文章《Android 8.1 从零开始写 HAL – (5) 添加执行权限》将介绍如何给 demoComponent HAL 添加必要的权限。

如果你急切地想看一看刚刚写好的 HAL 进程运行的样子,可以执行命令 setenforce 0 将设备的 SELinux 策略暂时关闭。 这样尽管系统仍然会报告权限错误,但不会禁止运行。

你可能感兴趣的:(嵌入式,Android)