调试概述
在 Android 13 AOSP 源码中创建 android.hardware.xxx HAL 服务,实现每 1 秒打印日志,并支持开机自启动。
设备: Pixel 7
系统版本: Android 13 (TQ2A.230505.002), userdebug
编译环境: OPENCODE + DEEPSEEEK V4 PRO
嘿兄弟and姐妹,如果你是Android源码级开发的同学我想你后面应该就不要看了,因为太基础,可以看看笔者这里写的一些想法,如果你是APP开发或者从业不久的同学我觉得你可以看看笔者的观点,项目+大模型将让你极大的降低学习的成本与难度。
一边打游戏 一边在干活 不敢想 真的不敢想
我就是给AI大模型下达命令,告诉他我的需求,然后我就一边打游戏一边给他输入一下sudo的密码以及是or否,他就自己调试,自己编译源码,自己fastboot img,自己push so文件验证,试想一下,要是我自己干的话,得不断地去试错,一篇一篇博客去看,没个几天都不一定能搞定,而且这还是自己调试情况,并不是在公司会有一个完整团队可以做协助,就2-3小时就干完了,我自己游戏也打的很爽,最后再让他生成一个调试报告、要有总结要有patch要有明确的结论,写的真是好。
对这个行业 笔者自己的一些想法
笔者已经好几年没写代码了,平时看日志看代码和其他组沟通会比较多,从去年开始就有同事给我说一些大模型有多牛,从我内心可接受度来说就是再牛不也得需要人来干嘛,我自己平时就用cursor帮我分析一下日志、用公司的skills帮我生成一份功耗性能报告或者帮我分析一下systrace,但总体来看增效的程度并不是很大,反而人少了活多了,更卷了,所以对这些大模型工具并不是太感兴趣,接受度不算高,其实应该还是skills没做好,其理论上确实可以替代一些人力,让人腾出手来去瑞幸坐坐聊聊天什么的。
不过有一点可以确定的是,这个行业内的一些伙伴确实得动一动了,其实笔者还是挺乐意看到这样的现象或许自己本身就是出身草莽又或许是觉得有些人确实质素太低了,容不下人、待人又刻薄、刚愎自用,但也只是笔者一家的书生之见,我还是挺佩服项目组一些大哥的,能扛事,专业知识又强、协作的过程中包容度又很高,我想行业后续对这些人的价值体现会越来越明显。
还要讲讲薪资,笔者一直认为在南京靠上班能拿个1w就已经很高了,行业好的时候,撸串的一个前同事对我说公司只给他20k他觉得看不起他,然后后续不停地要求涨1k涨1k,我真的不能理解,涨1k就能飞起来了吗?
AI大模型+人工review 的交付形式未来一定是这样的配置,这行的薪资会整体下降,专业领域知识体系完善的人会更有优势,未来写字楼会更加宽敞,有能力的公司可能都会加一层展示大厅与健身房,这也未必可知。
笔者的焦虑
其实笔者都想学点其他东西,比如学肉夹馍的制作、工艺品的加工以及在大学门口卖避孕套eg。
一、文件结构
hardware/interfaces/xxx/aidl/
├── Android.bp # aidl_interface 定义
├── android/hardware/xxx/
│ └── Ixxx.aidl # AIDL 接口: ping()
├── aidl_api/android.hardware.xxx/1/ # 冻结的 API dump (stable AIDL 必需)
│ ├── android/hardware/xxx/Ixxx.aidl
│ └── .hash
├── aidl_api/android.hardware.xxx/current/
│ └── android/hardware/xxx/Ixxx.aidl
└── default/
├── Android.bp # cc_binary 编译定义
├── xxx.h # BnXXX 实现头文件
├── xxx.cpp # 每 1s 日志线程实现
├── service.cpp # main() 入口, 注册 binder 服务
├── android.hardware.xxx-service.example.rc # init 启动脚本
└── android.hardware.xxx-service.example.xml # VINTF manifest
11 个文件,总计约 110 行代码。
二、技术方案
2.1 AIDL 方式选择
采用 stable AIDL(非 unstable):
@VintfStability注解stability: "vintf"+versions: ["1"]- 需要冻结的 API dump (
aidl_api/) +.hash文件 - 后端库名为
android.hardware.xxx-V1-ndk(带版本号)
2.2 核心实现
- xxx.cpp:构造函数中启动独立线程,循环打印日志,每 1 秒一次
- service.cpp:注册 binder 服务,失败时不崩溃仅打印警告,日志线程继续运行
- xxx.h :使用
std::atomic<bool>控制线程安全退出 - Ixxx.aidl :暴露
ping()方法,保持接口最小化
三、编译过程
3.1 编译步骤
bash
source build/envsetup.sh
lunch aosp_panther-userdebug # panther = Pixel 7 Pro
make android.hardware.xxx-service.example -j4
3.2 关键问题与解决
| 问题 | 原因 | 解决 |
|---|---|---|
undefined module android.hardware.xxx-V1-ndk |
stable AIDL 需要冻结的 API dump | 使用 aidl --dumpapi 生成冻结文件,并用正确算法计算 .hash |
| Soong bootstrap OOM (15.4GB < 16GB) | glob 再生占用内存过大 | 删除 out/soong 后耐心等待;globs 缓存后增量编译正常 |
hash 校验失败 checkhash_1.timestamp |
.hash 值计算错误 |
使用与编译系统相同的算法:sha1sum(排序后的 aidl 文件 sha1) + "latest-version" |
3.3 编译产物
out/target/product/panther/vendor/bin/hw/android.hardware.xxx-service.example # 二进制 20KB
out/soong/.../android.hardware.xxx-V1-ndk.so # NDK 后端 29KB
out/target/product/panther/vendor/etc/init/android.hardware.xxx-service.example.rc
out/target/product/panther/vendor/etc/vintf/manifest/android.hardware.xxx-service.example.xml
四、部署过程(关键结论)
4.1 Pixel 7 vendor.img 的特殊性
vendor.img 是 Google 预编译镜像,路径:
vendor/google_devices/panther/proprietary/vendor.img (593MB, ext4, shared_blocks)
编译系统声明:BOARD_PREBUILT_VENDORIMAGE := vendor/google_devices/panther/proprietary/vendor.img
构建 vendorimage 仅直接复制此预编译文件,不会打包任何源码编译的 vendor 文件。
4.2 失败尝试一:替换 vendor.img(❌ 不可行)
使用 mkfs.ext4 创建新镜像 → 复制原文件 + 注入新文件 → 刷入 → 设备 bootloop。
根因:
vendor.img使用了shared_blocks特性(ext4 ro_compat feature 0x4000),新创建的镜像缺少此特性,设备内核无法挂载- 主机内核不支持
shared_blocks读写挂载,无法直接修改原始镜像 debugfs直接写入文件可能损坏 shared_blocks 文件系统的引用计数,同样导致 bootloop
结论:不能通过创建新 ext4 镜像或 debugfs 修改来改变 vendor.img。
4.3 失败尝试二:安装到 system 分区(❌ 未完成)
尝试将 binary/.rc 安装到 /system 分区(该分区从源码构建),但因需要修改 device-panther.mk 触发完整 Soong bootstrap,在 15.4GB RAM 下反复 OOM 超时,未能在合理时间内完成。
4.4 成功方案:overlayfs + adb push(✅ 可行)
Pixel 7 的 userdebug 版本支持 overlayfs,通过 adb remount 在 vendor 分区上创建可写覆盖层:
bash
# 1. 启用 overlayfs
adb root && adb remount
# 2. 推送文件
adb push android.hardware.xxx-service.example /vendor/bin/hw/
adb push android.hardware.xxx-service.example.rc /vendor/etc/init/
adb push android.hardware.xxx-V1-ndk.so /vendor/lib64/
adb push android.hardware.xxx-service.example.xml /vendor/etc/vintf/manifest/
# 3. 修复 SELinux context
adb shell setenforce 0
adb shell chcon u:object_r:hal_memtrack_default_exec:s0 /vendor/bin/hw/android.hardware.xxx-service.example
# 4. 重启验证
adb reboot
adb logcat -e xxx # 每 1 秒输出日志
overlayfs 特性: 写入文件存储在 scratch 分区,重启后数据持久化,不会因 reboot 丢失。
五、SELinux 处理
5.1 问题
默认 vendor_file context 不允许 init 进程启动服务,报错:
init: Could not start service 'vendor.xxx-default':
File labeled "vendor_file" has incorrect label or no domain transition defined
5.2 临时解决
setenforce 0切换到 permissive 模式chcon u:object_r:hal_memtrack_default_exec:s0借用已有 HAL 的 context
5.3 正式解决(待实施)
需要添加正式 SELinux 策略:
bash
# device/google/pantah-sepolicy/panther/file_contexts
/vendor/bin/hw/android\.hardware\.xxx-service\.example u:object_r:hal_xxx_default_exec:s0
并创建对应的 .te 文件定义域转换规则。
六、开机自启验证
| 阶段 | 日志 | 说明 |
|---|---|---|
| Boot | init: Parsing file /vendor/etc/init/android.hardware.xxx-service.example.rc... |
init 解析了 rc 文件 |
| Boot | init: starting service 'vendor.xxx-default'... |
init 自动启动了服务 |
| Runtime | xxx HAL service is running... (每 1 秒) |
日志线程持续运行 |
| Runtime | servicemanager: Found android.hardware.xxx.Ixxx/default in device VINTF manifest. |
VINTF 识别成功 |
| Runtime | xxx HAL service registered, starting thread pool... |
Binder 注册成功 |
七、结论
7.1 已验证可行的
| 项目 | 状态 | 备注 |
|---|---|---|
| stable AIDL HAL 编译 | ✅ | 需要冻结 API + .hash |
| permissive SELinux 下运行 | ✅ | 需 setenforce 0 |
| VINTF manifest 识别 | ✅ | 推送 xml 到 /vendor/etc/vintf/manifest/ |
| Binder 服务注册 | ✅ | Ixxx/default |
| 每 1 秒打印日志 | ✅ | LOG(INFO) + thread |
| 开机自启动 | ✅ | overlayfs + rc 文件持久化 |
| 重启后数据持久化 | ✅ | overlayfs scratch 分区 |
7.2 当前限制
| 问题 | 影响 | 解决方案 |
|---|---|---|
| Pixel 7 vendor.img 是预编译 | 不能通过常规构建流程打包 | 使用 overlayfs / 或修改 build 流程将其放在 system 分区 |
| SELinux enforcing 下无法启动 | 需手动 setenforce 0 |
添加正式 SELinux 策略 |
| SELinux context 借用 hal_memtrack | 不规范的 context | 定义专用 hal_xxx context |
| 机器 RAM 不足 (15.4GB) | 全量 Soong bootstrap 超时 | 先用增量编译,或升级硬件 |
7.3 正式部署建议
如果要将此 HAL 正式集成到 ROM 中,推荐方案顺序:
-
推荐方案: 将 binary/.rc 安装到
system分区(而非 vendor)--- system.img 从源码构建- 修改
Android.bp:去掉vendor: true(默认安装到 system) - 修改
.rc路径:/system/bin/hw/替换/vendor/bin/hw/ - 添加
PRODUCT_PACKAGES到device-panther.mk - 添加 SELinux 策略
- 修改
-
备选方案: 解包原 vendor.img,保留 shared_blocks 特性,精确注入文件
- 使用支持 shared_blocks 的内核环境操作
- 或在设备端通过 recovery 注入
-
当前可用方案: overlayfs 部署,适合开发调试,不适合量产
patch
# xxx HAL --- 源码修改记录
## 修改概览
| # | 文件 | 操作 | 说明 |
|---|------|------|------|
| 1 | `hardware/interfaces/xxx/aidl/default/Android.bp` | 修改 | 去掉 `vendor: true`, 安装到 system |
| 2 | `hardware/interfaces/xxx/aidl/default/android.hardware.xxx-service.example.rc` | 修改 | 路径从 `/vendor/bin/hw/` 改为 `/system/bin/hw/` |
| 3 | `hardware/interfaces/xxx/xxx.mk` | 新建 | PRODUCT_COPY_FILES 到 system |
| 4 | `device/google/pantah/device-panther.mk` | 修改 | 加入 PRODUCT_PACKAGES + include |
| 5 | `system/sepolicy/public/hal_xxx.te` | 新建 | HAL binder 权限定义 |
| 6 | `device/google/pantah-sepolicy/panther/hal_xxx_default.te` | 新建 | 进程域定义 |
| 7 | `device/google/pantah-sepolicy/panther/file_contexts` | 修改 | 二进制 SELinux 标签 |
| 8 | `hardware/interfaces/xxx/aidl/default/service.cpp` | 修改 | CHECK_EQ → 非致命警告 |
---
## 详细修改
### 修改 1: `hardware/interfaces/xxx/aidl/default/Android.bp`
**改动:** 去掉 `vendor: true`,二进制、rc、vintf 全部安装到 system 分区。
```diff
--- a/hardware/interfaces/xxx/aidl/default/Android.bp
+++ b/hardware/interfaces/xxx/aidl/default/Android.bp
@@ -7,7 +7,6 @@ cc_binary {
relative_install_path: "hw",
init_rc: ["android.hardware.xxx-service.example.rc"],
vintf_fragments: ["android.hardware.xxx-service.example.xml"],
- vendor: true,
srcs: [
"service.cpp",
"xxx.cpp",
原因: Pixel 7 的 vendor.img 是 Google 预编译镜像,无法通过常规 build 打包。改为 system 分区(system.img 从源码构建)后可直接打包。
影响:
- 二进制安装到
/system/bin/hw/(原/vendor/bin/hw/) - init .rc 安装到
/system/etc/init/(原/vendor/etc/init/) - VINTF .xml 安装到
/system/etc/vintf/ - NDK 后端
.so链接 system 变体
修改 2: hardware/interfaces/xxx/aidl/default/android.hardware.xxx-service.example.rc
改动: 二进制路径改为 system 分区。
diff
--- a/hardware/interfaces/xxx/aidl/default/android.hardware.xxx-service.example.rc
+++ b/hardware/interfaces/xxx/aidl/default/android.hardware.xxx-service.example.rc
@@ -1,4 +1,4 @@
-service vendor.xxx-default /vendor/bin/hw/android.hardware.xxx-service.example
+service vendor.xxx-default /system/bin/hw/android.hardware.xxx-service.example
class hal
user nobody
group nobody
修改 3: hardware/interfaces/xxx/xxx.mk(新建)
makefile
PRODUCT_COPY_FILES += \
hardware/interfaces/xxx/aidl/default/android.hardware.xxx-service.example.rc:$(TARGET_COPY_OUT_SYSTEM)/etc/init/android.hardware.xxx-service.example.rc \
hardware/interfaces/xxx/aidl/default/android.hardware.xxx-service.example.xml:$(TARGET_COPY_OUT_SYSTEM)/etc/vintf/manifest/android.hardware.xxx-service.example.xml
修改 4: device/google/pantah/device-panther.mk
改动: 文件末尾添加 3 行。
diff
--- a/device/google/pantah/device-panther.mk
+++ b/device/google/pantah/device-panther.mk
@@ -348,3 +348,7 @@ PRODUCT_COPY_FILES += \
# Enable adpf cpu hint session for SurfaceFlinger
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
debug.sf.enable_adpf_cpu_hint=true
+
+# xxx HAL service
+PRODUCT_PACKAGES += android.hardware.xxx-service.example
+include hardware/interfaces/xxx/xxx.mk
修改 5: system/sepolicy/public/hal_xxx.te(新建)
te
binder_call(hal_xxx_client, hal_xxx_server)
binder_call(hal_xxx_server, hal_xxx_client)
hal_attribute_service(hal_xxx, hal_xxx_service)
binder_call(hal_xxx_server, servicemanager)
hal_attribute_hwservice(hal_xxx, hal_xxx_hwservice)
作用: 定义 HAL 进程的 binder 通信权限、service 属性、hwservice 属性。
修改 6: device/google/pantah-sepolicy/panther/hal_xxx_default.te(新建)
te
type hal_xxx_default, domain;
hal_server_domain(hal_xxx_default, hal_xxx)
type hal_xxx_default_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(hal_xxx_default)
作用: 定义 hal_xxx_default 进程域和执行文件类型,允许 init 进程启动此服务。
修改 7: device/google/pantah-sepolicy/panther/file_contexts
diff
--- a/device/google/pantah-sepolicy/panther/file_contexts
+++ b/device/google/pantah-sepolicy/panther/file_contexts
@@ -2,3 +2,6 @@
/dev/ttySAC18 u:object_r:hci_attach_dev:s0
/dev/logbuffer_btlpm u:object_r:logbuffer_device:s0
/dev/logbuffer_tty18 u:object_r:logbuffer_device:s0
+
+# xxx HAL
+/system/bin/hw/android\.hardware\.xxx-service\.example u:object_r:hal_xxx_default_exec:s0
作用: 给二进制文件打 SELinux 标签 hal_xxx_default_exec,init 可以执行并过渡到 hal_xxx_default 域。
修改 8: hardware/interfaces/xxx/aidl/default/service.cpp
diff
--- a/hardware/interfaces/xxx/aidl/default/service.cpp
+++ b/hardware/interfaces/xxx/aidl/default/service.cpp
@@ -14,9 +14,12 @@ int main() {
const std::string instance = std::string() + xxx::descriptor + "/default";
binder_status_t status =
AServiceManager_addService(xxx->asBinder().get(), instance.c_str());
- CHECK_EQ(status, STATUS_OK);
+ if (status != STATUS_OK) {
+ LOG(WARNING) << "xxx HAL service registration failed, but logging thread is alive.";
+ } else {
+ LOG(INFO) << "xxx HAL service registered, starting thread pool...";
+ }
- LOG(INFO) << "xxx HAL service registered, starting thread pool...";
ABinderProcess_joinThreadPool();
return EXIT_FAILURE;
原因: CHECK_EQ 在注册失败时会 abort,改用非致命警告使服务即使注册失败也能持续运行日志线程。
编译和部署
编译
bash
source build/envsetup.sh
lunch aosp_panther-userdebug
make android.hardware.xxx-service.example -j4
make systemimage -j4
刷机
bash
adb reboot fastboot
fastboot flash system out/target/product/panther/system.img
fastboot reboot
验证
bash
adb logcat -e xxx
# 预期输出: "xxx HAL service is running..." 每 1 秒
受影响的文件清单
hardware/interfaces/xxx/aidl/default/Android.bp (修改)
hardware/interfaces/xxx/aidl/default/android.hardware.xxx-service.example.rc (修改)
hardware/interfaces/xxx/aidl/default/service.cpp (修改)
hardware/interfaces/xxx/xxx.mk (新建)
device/google/pantah/device-panther.mk (修改, 末尾加3行)
system/sepolicy/public/hal_xxx.te (新建)
device/google/pantah-sepolicy/panther/hal_xxx_default.te (新建)
device/google/pantah-sepolicy/panther/file_contexts (修改, 末尾加2行)
未修改的新增文件(第一次创建时已存在)
hardware/interfaces/xxx/aidl/Android.bp (aidl_interface, V1)
hardware/interfaces/xxx/aidl/android/hardware/xxx/Ixxx.aidl
hardware/interfaces/xxx/aidl/aidl_api/android.hardware.xxx/1/ (冻结API)
hardware/interfaces/xxx/aidl/default/xxx.h
hardware/interfaces/xxx/aidl/default/xxx.cpp
hardware/interfaces/xxx/aidl/default/android.hardware.xxx-service.example.xml