35、Treble架构调试:HAL接口、hidl服务、VINTF、兼容性测试
Treble架构,说白了就是Google在Android 8.0搞的一次大手术。把原来铁板一块的Framework和厂商底层实现,硬生生切成了两半。为什么要这么干?你想想看,以前每次Android大版本升级,芯片厂商都得重新适配一遍,累死累活。Treble之后,Framework和vendor分家,升级就快多了。
但分家也有分家的烦恼。接口多了,调试起来就复杂了。我这些年跟Treble打交道,踩过的坑真不少。今天咱们就聊聊,怎么在Treble架构下做调试。
HAL接口:从传统到Binder化
传统HAL是so库,直接dlopen加载。Treble之后,HAL变成了HIDL服务,跑在独立进程里。这变化,调试方式完全不同了。
传统HAL出问题,我一般直接看logcat,搜“HAL”关键字。但HIDL服务出问题,你得先确认服务有没有起来。
核心命令:
# 查看所有注册的HIDL服务
adb shell lshal
# 查看特定服务是否存活
adb shell lshal | grep camera
# 查看服务进程
adb shell ps -A | grep hwservicemanager
我记得有一次,camera HAL死活打不开。我查了半天log,发现服务根本没注册。后来用lshal一看,果然没有camera provider。最后定位到是selinux权限问题,服务进程被杀了。
我的习惯:调试HAL之前,先跑一遍lshal,确认所有服务都在。这一步能省掉你一半的排查时间。
HIDL服务:调试三板斧
HIDL服务跑在独立进程里,调试起来比传统HAL麻烦。我总结了三板斧:
- 看log:HIDL服务的log默认打到logcat里,但有些厂商会重定向。我建议直接看
/dev/log或者logcat -b all。 - 查状态:用
dumpsys或者lshal --debug,能拿到服务的内部状态。 - 抓调用:用
systrace或者perfetto,能看到HIDL调用的耗时。
举个例子,我曾经遇到一个audio HAL的问题,声音断断续续。我打开systrace,发现每次音频播放时,HIDL调用耗时都在100ms以上。这明显不正常。后来定位到是底层驱动锁竞争,改了调度策略就好了。
注意:HIDL服务如果crash了,hwservicemanager会自动重启它。但重启过程中,所有依赖这个服务的客户端都会收到死亡通知。如果你的app突然卡死,先看看是不是HAL服务重启了。
VINTF:兼容性检查的命门
VINTF(Vendor Interface)是Treble的“契约”。它定义了vendor和Framework之间的接口约定。说白了,就是一份清单,告诉系统:我支持哪些HAL,版本是多少。
VINTF文件在/vendor/etc/vintf/目录下,主要有两个:
manifest.xml:厂商声明自己实现了哪些HALcompatibility_matrix.xml:Framework声明自己需要哪些HAL
系统启动时,会比对这两份文件。如果对不上,系统会报错,甚至直接不进系统。
调试VINTF问题:
# 检查VINTF是否匹配
adb shell vintf --check
# 查看当前系统的VINTF信息
adb shell dumpsys vintf
# 查看manifest
adb shell cat /vendor/etc/vintf/manifest.xml
我曾经遇到一个坑:升级了HAL版本,但忘了更新manifest.xml。结果系统启动时,Framework发现版本不匹配,直接拒绝加载。查了半天log,才看到vintf --check报的错。嗯,从那以后,我每次改HAL接口,第一件事就是更新manifest。
兼容性测试:CTS/VTS
Treble架构下,兼容性测试分两套:
- CTS(Compatibility Test Suite):测Framework和app的兼容性
- VTS(Vendor Test Suite):测vendor实现的兼容性
VTS是Treble特有的。它直接测试HIDL接口,确保厂商的实现符合规范。
跑VTS的命令:
# 跑所有VTS测试
adb shell vts-tradefed run vts
# 跑特定模块的测试
adb shell vts-tradefed run vts -m VtsHalCameraProviderV2_4TargetTest
我建议你重点关注VTS的测试结果。如果VTS没过,说明你的HAL实现有问题。别想着绕过,CTS也会卡你。
我的经验:VTS测试失败,90%的原因是接口实现不完整。比如某个方法返回了UNKNOWN_ERROR,或者参数校验没做。仔细看测试log,一般都能找到线索。
实战:调试一个HIDL服务crash
咱们来走一遍完整的调试流程。假设camera HAL服务crash了。
- 确认服务状态:
lshal | grep camera,发现没有输出。 - 看log:
logcat -b all | grep -i camera,看到FATAL EXCEPTION。 - 抓tombstone:
adb pull /data/tombstones/,分析crash堆栈。 - 查VINTF:
vintf --check,确认manifest没问题。 - 复现并抓trace:
perfetto -t 10s -o /data/misc/perfetto/trace,分析调用链路。
我记得有一次,crash堆栈指向了内存越界。我查了半天,发现是HIDL接口传了一个空指针,服务端没做判空。嗯,这种问题,加个if (ptr == nullptr) return error;就解决了。
SVG:Treble调试知识体系
总结
Treble调试,核心就三件事:
- 接口契约:VINTF文件必须对得上,否则系统不认
- 服务状态:HIDL服务必须活着,否则功能不可用
- 兼容性验证:VTS必须过,否则CTS也过不了
我个人习惯,每次改完HAL接口,先跑一遍vintf --check,再跑一遍VTS。这两步过了,基本就没大问题了。如果还有问题,那就老老实实看log,抓trace,一步步排查。
嗯,Treble调试其实没那么玄乎。把基础工具用好,把流程走顺,大部分问题都能搞定。
公众号:蓝海资料掘金营,微信deep3321