设备树踩坑记:Pearl 开发实录
本文基于 Xiaomi-Pearl-Development/android_device_xiaomi_pearl 的 commit 整理,目标 ROM 为 LineageOS 22.2 (Android 15),设备为 Redmi Note 12T Pro (codename: pearl),SoC 为 MediaTek Dimensity 8200 Ultra (MT6896)。
1. SELinux Permissive:三种方法都不省心
坑 1:内核命令行参数在 DSU 下不生效
最初尝试在 BoardConfig.mk 中添加:
BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive问题:在 DSU(Dynamic System Updates)环境下这个参数不生效。DSU 有自己的启动流程,会忽略部分内核命令行参数。
尝试的解决方案:改为在 init.pearl.rc 中写入:
on early-init write /sys/fs/selinux/enforce 0结果:这需要额外的 SELinux 权限 allow init kernel:security setenforce,形成鸡生蛋的问题——你要关 SELinux 先得有 SELinux 权限。
最终方案:直接使用 SELINUX_IGNORE_NEVERALLOWS := true(开发阶段),后来在 sepolicy 基本完成后移除。
教训:DSU 是开发利器,但 SELinux 相关的内核命令行参数在 DSU 下可能不生效。开发初期直接用
SELINUX_IGNORE_NEVERALLOWS最省事,但记得在提交前移除。实际上,SeLinux Permissive的相关配置在我的开发中基本没有生效,这是MediaTek的问题。
2. keymint-mitee 服务启动失败
坑 2:Could not start service 'vendor.keymint-mitee' as part of class 'early_hal'
现象:开机后 keymint 服务无法启动,导致指纹、锁屏等功能全部失效。
原因:vendor.keymint-mitee 是 Xiaomi 私有的 TEE keymint 实现,默认的 service 定义不完整,缺少 interface 声明。
解决方案:在 init.pearl.rc 中 override 这个服务:
service vendor.keymint-mitee /vendor/bin/hw/android.hardware.security.keymint@1.0-service.mitee override class early_hal interface android.hardware.keymaster@4.0::IKeymasterDevice default interface android.hardware.keymaster@4.1::IKeymasterDevice default user system group system drmrpc seclabel u:r:hal_keymint_default:s0 disabled
on boot enable vendor.keymint-mitee教训:MTK 平台的 TEE 实现(mitee)需要手动 override 服务定义并添加
interface声明。如果看到 “Could not start service” 错误,先检查服务定义是否完整。
3. 内核模块:多了会出事
坑 3:添加 xm_power_debug.ko 后需要 revert
过程:
原因:这个模块不是必需的,而且可能导致启动问题。
教训:内核模块不要随意添加。只加载设备实际需要的模块。如果不确定,先不加,等出现问题再按需添加。多余的模块可能:
- 增加启动时间
- 引发内核 panic
- 与其他模块冲突
4. Thermal 服务崩溃
坑 4:android.hardware.thermal-service.mediatek 导致系统崩溃
现象:添加 thermal HAL 后系统崩溃。
过程:
- 添加了
android.hardware.thermal-service.mediatek和thermal_info_config.json - 系统崩溃
- commit
1bf46cb:revert 整个 thermal 配置
原因:thermal config 文件与设备的硬件不匹配,thermal zone 路径或阈值配置错误。
教训:thermal 配置需要精确匹配硬件。错误的 thermal config 会导致系统崩溃甚至硬件损坏。建议:
- 先从同 SoC 的其他设备树复制
- 逐步调整参数
- 测试时注意温度监控
5. Blob 命名冲突:fingerprint HAL
坑 5:fingerprint blob 命名冲突导致 HAL 无法加载
现象:指纹功能不工作。
原因:从 stock ROM 提取的 fingerprint.fpc.so 与系统中的 ODM HAL 命名冲突。
解决方案(commit ee2dea9):
vendor/lib64/hw/fingerprint.fpc.sovendor/lib64/hw/fingerprint.fpc.so:vendor/lib64/hw/fingerprint.fpc.default.so;FIX_SONAME将 blob 重命名为 fingerprint.fpc.default.so 并修复 SONAME。
教训:Xiaomi 的 ODM 分区可能包含同名的 HAL blob。当 blob 无法加载时,检查是否有命名冲突。解决方案是重命名并用
FIX_SONAME修复动态链接。同样的问题也出现在audio.primary.mediatek.so上。
6. fstab 配置:细节决定成败
坑 6:fstab 格式错误和参数不当
问题 1:fstab 拼写错误(commit c39ddee)
问题 2:userdata 分区的 resize 标志导致问题(commit 9524ecf):
wait,check,formattable,quota,resize,latemountwait,check,formattable,quota,latemount问题 3:metadata 分区需要 data=journal,commit=1(commit a1767d0):
noatime,nosuid,nodev,discardnoatime,nosuid,nodev,discard,data=journal,commit=1教训:fstab 是最容易出错的文件之一,因为:
- 格式严格,多一个空格都可能出问题
- 参数顺序和组合影响挂载行为
- 不同设备的分区参数可能不同
- 建议从同 SoC 设备复制后逐项检查
7. 虚拟接近传感器:一个功能改了 5 个 commit
坑 7:Pearl 没有物理接近传感器
Pearl 没有物理接近传感器,需要使用虚拟接近传感器。这个功能的实现涉及 5 个 commit:
3d6efa0:添加 sepolicy for proximity sensor13f395b:setup overlay for pearl6dbd948:setup policy for virtual proximityf4d1bee:add file contexts for virtual proximity26b7859:fixup virtual proximity sensor(最终修复)
关键修复(commit 26b7859):
/dev/mius(.*)? u:object_r:sensors_device:s0 /sys/bus/iio/devices u:object_r:sysfs_tp_virtual_prox:s0 /sys/devices/platform/us_prox.0/iio:device4(/.*)? u:object_r:sysfs_tp_virtual_prox:s0
# sepolicy/vendor/hal_sensors_default.te allow hal_sensors_default iio_device:chr_file r_file_perms; allow hal_sensors_default sysfs_tp_virtual_prox:dir r_dir_perms;教训:虚拟接近传感器需要:
- 正确的
file_contexts(设备节点路径)- 正确的 SELinux 策略(对 iio_device 和 sysfs 的访问权限)
- 正确的 property 配置(
persist.vendor.fingerprint.sensor_location)- 传递 display ID 到 sensor location
这是一个典型的”多层配置都要对”的案例。
8. 指纹支付:微信 SoterService
坑 8:微信指纹支付不工作
现象:指纹功能正常,但微信指纹支付无法使用。
解决方案(commit 29d9955):添加 SoterService:
PRODUCT_PACKAGES += \ SoterService原因:微信使用 SOTER(Secure Online TEE-based biometric Authentication)框架进行指纹支付验证,需要 SoterService 支持。
教训:指纹功能和指纹支付是两回事。指纹支付需要:
- 正确的 TEE 实现(mitee)
- SoterService
- IFAAService(支付宝/微信的 IFaa 认证)
9. VINTF 清理:HAL 声明不能多也不能少
坑 9:VINTF manifest 中的冗余声明
commit 8903f3d:cleanup vintf and Kill 2ND arch
问题:VINTF manifest 中声明了设备不支持的 HAL,或者有冗余的 HAL 声明。
教训:VINTF manifest 应该只声明设备实际提供的 HAL。多余的声明会导致:
- CTS 测试失败
- 框架尝试调用不存在的 HAL
- 启动时的 VINTF 兼容性检查失败
10. Recovery 触摸固件
坑 10:Recovery 模式下触摸不工作
commit 8885235:Add touchscreen firmware for recovery
问题:在 recovery 模式下触摸屏不工作,无法通过触摸操作 recovery。
解决方案:将触摸屏固件添加到 recovery ramdisk。
教训:Recovery 模式需要单独的驱动和固件支持。如果 stock ROM 的 recovery 支持触摸,移植时需要确保固件也被包含。
11. 移除不必要的东西
坑 11:Xiaomi 私有服务不都是必需的
Pearl 移除的不必要组件:
| 组件 | 原因 |
|---|---|
displayfeature | Xiaomi 私有显示服务,LineageOS 不需要 |
vibratorfeature | Xiaomi 私有振动器服务 |
| Power-off Alarm | 功能不完整 |
| 多余的 kernel modules | 引发问题 |
| 32-bit blob | 设备不需要 |
教训:不要盲目复制 stock ROM 的所有组件。很多 Xiaomi 私有服务在 AOSP/LineageOS 环境下不工作或不需要。逐个测试,不工作的就移除。
12. Blob Fixup 常见模式
从 Pearl 的开发中总结出的 blob fixup 常见模式:
12.1 重命名 + FIX_SONAME
当 blob 与系统中已有 HAL 命名冲突时:
vendor/lib64/hw/fingerprint.fpc.so:vendor/lib64/hw/fingerprint.fpc.default.so;FIX_SONAMEvendor/lib64/hw/audio.primary.mediatek.so;SYMLINK=vendor/lib64/hw/audio.primary.mt6895.so12.2 符号链接
当 blob 期望在特定路径找到时:
vendor/lib64/hw/mt6895/camerahalserver;SYMLINK=vendor/bin/hw/camerahalserver12.3 禁用 ELF 检查
当 blob 的 ELF 格式不标准时:
vendor/lib64/libHalSuperSensorServer.so;DISABLE_CHECKELF12.4 仅生成复制规则
当 blob 只需要在构建时复制,不需要运行时检查:
vendor/bin/crossbuild/DataSet/...;MAKE_COPY_RULE_ONLY13. 开发流程建议
基于 Pearl 的经验,建议的开发流程:
Phase 1:能开机就行
- 使用 prebuilt kernel
- 配置最基础的 fstab
- 设置 SELinux permissive(
SELINUX_IGNORE_NEVERALLOWS := true) - 确保能进入系统(即使很多功能不工作)
Phase 2:基础功能
- WiFi
- 蓝牙
- 显示
- 触摸
Phase 3:核心功能
- 指纹
- 相机
- NFC
- 音频
Phase 4:调试与修复
- 逐个修复 blob 问题
- 处理 SELinux 拒绝
- 测试所有功能
Phase 5:清理
- 移除不必要的组件
- 合并到 common tree
- 从 permissive 切换到 enforcing
14. 调试技巧
14.1 SELinux 拒绝
# 收集所有 avc 拒绝adb shell dmesg | grep avc | grep denied
# 生成策略规则adb shell dmesg | grep avc | audit2allow -p policy
# 查看特定进程的拒绝adb shell dmesg | grep avc | grep hal_fingerprint14.2 HAL 服务问题
# 查看 HAL 服务状态adb shell service list | grep hal
# 查看 HAL 进程是否运行adb shell ps -A | grep hal
# 查看 HAL 服务日志adb logcat -s hal_fingerprint14.3 内核模块问题
# 查看已加载模块adb shell lsmod
# 查看模块加载日志adb shell dmesg | grep insmod
# 查看模块依赖adb shell modinfo /vendor/lib/modules/xxx.ko14.4 Blob 依赖问题
# 查看 blob 依赖readelf -d vendor/lib64/hw/xxx.so | grep NEEDED
# 查看 blob 的 SONAMEreadelf -d vendor/lib64/hw/xxx.so | grep SONAME
# 检查符号链接ls -la vendor/lib64/hw/15. 时间线:commit 的故事
整个开发过程约 2 周(2025-08-31 至 2025-09-14)。
工作量分布:
- Blob fixup:~30% 的 commit
- SELinux 策略:~25% 的 commit
- HAL 配置:~20% 的 commit
- 清理/重构:~15% 的 commit
- 其他:~10%
最耗时的部分:
- Blob 调试(反复试错)
- SELinux 策略(每次改一点)
- 虚拟接近传感器(5 个 commit 才搞定)