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 是指 Android.bp
(当然也可以使用 Android.mk
,语法稍有区别)。
在 default/
目录下新建文件 Android.bp
,内容如下:
/*****************************************************************************
* Copyright (C) 2020 Qidi.Huang
*
* Brief:
* Build demo service into an executable binary.
*
* Author: qidi_huang@hotmail.com
*****************************************************************************/
cc_defaults {
name: "demoSvc_v1_0_default",
shared_libs: [
"libhidlbase",
"libhidltransport",
"liblog",
"libutils",
"libhardware",
"libbinder",
"vendor.harman.hardware.demoComponent.demoService@1.0_vendor",
],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
}
cc_binary {
name: "vendor.harman.demoComponent.demoService@1.0-service",
defaults: ["demoSvc_v1_0_default"],
init_rc: ["vendor.harman.demoComponent.demoService@1.0-service.rc"],
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",
"vendor.harman.hardware.demoComponent.demoService@1.0_vendor"
],
}
目标 demoSvc_v1_0_default
可以理解成是将和 Binder 框架相关的库打包而成的一个总的库文件,vendor.harman.hardware.demoComponent.demoService@1.0_vendor
是通过接口描述文件自动生成的,同样可以在 /out/soong/.intermediates/...
目录下找到;
目标 vendor.harman.demoComponent.demoService@1.0-service
就是最终要生成的可执行文件;
属性 vendor: true
表示这是一个自定义的文件;
属性 relative_install_path: "hw"
和前一个属性共同作用,表示生成文件的相对存放位置在 out/target/product/<ProductName>/vendor/bin/hw/
目录;
属性 srcs
属性下包含了我们在之前几篇文章里编写的所有源文件 —— DemoService.cpp
、DemoServiceImpl.cpp
、BpDemoService.cpp
和 BnDemoService.cpp
。
如果不想过多关注,简单按照这个 Makefile 的格式,相应把各位置的文件名改成你自己的文件名也是可行的。
基于上述的 Makefile 在 default/
目录下**手动(mm
命令)**进行编译,我们能得到名为 vendor.harman.demoComponent.demoService@1.0-service
的可执行文件。为了让 demoComponent HAL 随系统启动而启动,我们还需要编写 *.rc
脚本,并在脚本中标注进程名、可执行文件、用户组等信息。
一般以可执行文件名作为脚本名,也就是 vendor.harman.demoComponent.demoService@1.0-service.rc
。
在 default/
目录下新建脚本,内容如下:
service MyDemoService /vendor/bin/hw/vendor.harman.demoComponent.demoService@1.0-service
class main
user system
group system
capabilities sys_nice net_bind_service net_admin net_raw
关键字 service
用来定义一个进程(或称为本地服务),后面第一个参数 MyDemoService
是进程名,第二个参数是可执行文件的绝对路径;
class main
表示把 MyDemoService
归属到 main 类;
user system
和 group system
表示 MyDemoService
的用户和组用户都是 system;
capabilities
指定了一些权限相关的属性。
要实现 demoComponent HAL 随系统启动而启动,需要将它的 可执行文件
和 *.rc
文件都打包进系统镜像。通过修改产品的 Makefile 可以实现这一目的。
先在 /device/<CompanyName>/<PlatformName>/common/
路径下为 demoComponent HAL 新建一个名为 demoComponent/
的专属目录,再在这个目录下创建名为 device_demoComponent.mk
的 Makefile。(其实叫什么名字都可以,但是用 demoComponent 更直观)
如此一来我们就有了 /device/harman/broxton/common/demoComponent/device_demoComponent.mk
。 除去注释,Makefile 内容只有一句话:
############################
# DemoService
############################
PRODUCT_PACKAGES += vendor.harman.demoComponent.demoService@1.0-service
这句话表示要将可执行文件 vendor.harman.demoComponent.demoService@1.0-service
打包进系统镜像,确切地说是打包进 vendor.img
。
切记,不要忘了把我们新建的 Makefile 添加到产品的 Makefile 中。 产品 Makefile 一般位于 /device/<CompanyName>/<PlatformName>/<ProductName>/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 不能按照预期工作,甚至连自启动都做不到。相反,我们会在 logcat
或 dmesg
里发现有很多日志提示我们没有操作权限。 下一篇文章《Android 8.1 从零开始写 HAL – (5) 添加执行权限》将介绍如何给 demoComponent HAL 添加必要的权限。
如果你急切地想看一看刚刚写好的 HAL 进程运行的样子,可以执行命令 setenforce 0
将设备的 SELinux
策略暂时关闭。 这样尽管系统仍然会报告权限错误,但不会禁止运行。