02 - AAOS 官方 VHAL 工具链

AOSP packages/services/Car + hardware/interfaces/automotive 仓库里,Google 官方维护的 VHAL 调试/模拟/测试工具。结论先行:小米团队有一半官方能力没用足——尤其”按 prop 名字注入”和”错误码注入”,直接解决 P1(propId 难记)和 P6(异常状态难模拟),且零成本(纯 adb)。

解决痛点:P1 propId 难记 / P2 areaId 语义 / P5 命令冗长 / P6 异常状态 / P7 难离车(部分)


1. 先理清”分层”——决定每个工具能测什么

小米当前两类注入命令处在不同层级01 篇 §2 已给表,这里展开原理):

App (CarPropertyManager)
    ↑ Binder
CarService (Java)  ←─① inject-vhal-event 在这里"半路截胡"
    ↑ HAL binder
VHAL 进程 (IVehicle/micar)  ←─② --mock_from_car 在这里
    ↑
vehiclecore → MCU/CAN
  • inject-vhal-event:在 CarService 内部直接调 HalService.onPropertyChangeVHAL 进程本身不知道。能骗过所有 CarPropertyManager 订阅者,但测不了 VHAL 自身的订阅/回调逻辑。
  • --mock_from_car:在 VHAL 进程的 dump() 里注入,经过完整 HAL binder 扇出给 CarService。能测 VHAL→CarService 链路。

这条分层认知是后续选型的前提:测 App UI 任选其一;测 VHAL/vehiclecore 必须下沉到 ② 或更深。


2. cmd car_service 全家桶——小米没用足的官方命令

入口源码:packages/services/Car/service/src/com/android/car/CarShellCommand.java(4663 行)。小米 11 篇只记了 inject-vhal-event/publish-vhal-event以下子命令都没用

子命令作用注入层user 版解决痛点
inject-vhal-event <名|ID> [area] <val> [-t delay]注入 VHAL 事件CarServiceP1/P5
inject-error-event <名|ID> <area> <errorCode>注入错误事件CarServiceP6
inject-continuous-events <ID> <val> [-s rate] [-d dur]按采样率持续注入CarService模拟连续信号
get-property-value <名|ID> [area]读 propHAL部分P1
set-property-value <名|ID> <area> <val>写 prop(走真实 HAL)HAL部分
get-carpropertyconfig <名|ID>查 CarPropertyConfigCarServiceP2
list-vhal-props列所有 propIdCarServiceP1
get-vhal-backendAIDL/HIDLCarServiceP3
check-fake-vhal是否连 FakeVHALCarService
emulate-driving-state [park|drive|reverse|neutral]驾驶态聚合注入(自动 inject 车速+挡位+手刹)CarService场景编排
day-night-mode / garage-mode / silent-mode模式模拟CarService场景

3. ⭐ HalPropertyDebugUtils——告别 16 进制,按”名字”注入(解决 P1)

这是本次调研最高 ROI 的发现CarShellCommand 里所有 propId 参数都走 decodePropertyId()(源码 HalPropertyDebugUtils.java):

private static int decodePropertyId(String propertyIdString) {
    if (toPropertyId(propertyIdString) != null)   // 先按名字查
        return toPropertyId(propertyIdString).intValue();
    return Integer.decode(propertyIdString);       // 再按 16/10 进制
}

AOSP 上可以这么写(不用背 0x1120040a):

adb shell cmd car_service inject-vhal-event ABS_ACTIVE 0 1
adb shell cmd car_service set-property-value HVAC_TEMPERATURE_SET ROW_1_LEFT 22.0
adb shell cmd car_service get-property-value PERF_VEHICLE_SPEED
adb shell cmd car_service inject-error-event SEAT_MEMORY_SELECT ROW_1_LEFT 2   # ERROR

输出侧会打印 ABS_ACTIVE(0x1120040a) 这种**“名字(16进制)“双语格式**。

小米的缺口与对策

  • 缺口:AOSP 的名字字典只覆盖 SYSTEM_PROPERTY;小米 vendor 私有 prop(0x6xxxxxxx 系列 3791 个)没有名字映射,仍要手填数字。
  • 对策(高 ROI):推动 micar vendor VHAL 把自定义 propId 注册进 HalPropertyDebugUtils(或在 App 侧维护一份 名字↔propId 表,包一个 micar-inject <名字> <值> 脚本)。这一步做完,团队调试效率直接翻倍。
  • 链接:service/src/com/android/car/hal/property/HalPropertyDebugUtils.javacs.android.com

4. vhal_emulator.py——官方 Python 注入库(真机不可用,但设计可抄)

AOSP packages/services/Car/tools/emulator/ 维护的 Python 模块,从 host 通过 ADB 端口转发(固定端口 33452) 连设备端 DefaultVehicleHal 的 SocketComm,protobuf 收发。

# 官方唯一"一行代码模拟异常态"的工具
vhal.setProperty(prop, area_id, value, status=AVAILABLE)  # status 可传 UNAVAILABLE/ERROR

同目录还有:prop_event_simulator.py(按名字注入 CLI)、vhal_prop_simulator.py(持续模拟驾驶/用户事件)、driving_info_generator.py(GPX 轨迹回放为车信号)、gui.py(PyQt4 GUI,无 GUI 痛点的官方原型)。

致命局限:依赖设备端 VHAL 是 DefaultVehicleHal + FakeVehicleHardware 并开了 SocketComm。小米真机 vendor VHAL 是自研 micar没开 SocketComm,直接用连不上 33452。真机不可用(除非改整机源码集成)。

值得抄的setProperty(status=...) 这一行 API 设计——比小米 --mock_from_car --stat 0/1/2 用数字更清晰。自研 mock 工具时可借鉴。


5. FakeVehicleHardware + vhalconfig JSON(模拟器侧,详见 04 篇

AOSP 默认 VHAL 的”假硬件”参考实现,用内存 map 存 prop 值。Android 14+ 支持零代码加自定义 prop

# 放 /vendor/etc/automotive/vhalconfig/xiaomi.json 定义小米 3791 自定义 prop
# 无需改 VHAL 源码,CF/模拟器启动即支持
adb root && adb shell setprop persist.vendor.vhal_init_value_override 1 && adb reboot

这是小米 3791 prop 落地到离线环境的载体,深度见 04 模拟器篇


6. car-test-lib——应用层单测官方桩(详见 07 篇

路径 packages/services/Car/libs/car-test-lib/(注意是 libs/ 下),提供 FakeCar/FakeCarPropertyService/CarPropertyController纯 JVM 跑,给 Controller 补单测。是 P9(应用层难自动化测试)的官方解药之一,落地评估见 07 篇


7. ⭐ 最被低估:Android 16 GRPCVehicleHardware——“插着真机但脱离 CAN 调试”

AOSP 16 给 IVehicleHardware 增加了 gRPC 远端实现(hardware/interfaces/automotive/vehicle/aidl/impl/grpc/):

真机 AAOS 的 VHAL 变成代理(proxy)
        ↓ gRPC
开发机上的 gRPC server(任意语言写信号源)

战略价值:让真机上的 VHAL 把 prop 请求转发给开发机的 gRPC server,实现**“插着真车机镜像、但完全脱离真实 CAN/MCU”调试**——比 vhal_emulator.py 的 SocketComm 现代得多,是 Google 官方的”云真机/信号源中心化”方向。

对小米:若升级到 Android 16 + 利用 newton/YU7 已有的多 VM 虚拟化,可在 host VM 跑一个 gRPC server 做开发期信号源,让 guest AAOS 的 VHAL 转发。建议单独立项评估升级 Android 16 的可行性——这可能比任何单点工具都更能根治”难脱离真车”(P7)。


8. 小米落地结论

优先级方案解决痛点门槛行动
TOP1 立刻做cmd car_service 按名字注入 + inject-error-event + emulate-driving-stateP1/P5/P6纯 adb(userdebug)团队 SOP 从 --mock_from_car 切到 cmd car_service <名字>;推动 micar vendor prop 注册进 HalPropertyDebugUtils
TOP2 战略投入Android 16 GRPCVehicleHardwareP7升级 A16 + 多 VM立项评估”真机代理 + 开发机信号源”
TOP3 应用层补强car-test-lib 给 Controller 补单测P9加 gradle 依赖07 篇
不推荐直接用vhal_emulator.py改整机源码真机没 SocketComm,仅抄其 setProperty(status) 设计

与小米现有工具的对应关系

小米现有AOSP 官方对应提升点
dumpsys car_service inject-vhal-event(就是它本身)配 HalPropertyDebugUtils 后可按名字
dumpsys ...IVehicle/micar --mock_from_cardumpsys ...IVehicle/default --set/--getAOSP 版支持 --help + 名字,建议推动 micar dump 标准化
CarDemo4Test.apktools/emulator/gui.py + car-test-lib官方版可脱离设备/持续维护
LogPropMonitor.pylist-vhal-props + get-property-value官方版自带名字字典

附:AOSP 关键路径速查

路径作用
packages/services/Car/service/src/com/android/car/CarShellCommand.javacmd car_service 全部子命令源
packages/services/Car/service/src/com/android/car/hal/property/HalPropertyDebugUtils.javapropId 名字↔ID 互转
packages/services/Car/tools/emulator/vhal_emulator.py + 配套
packages/services/Car/libs/car-test-lib/src/android/car/testapi/FakeCar / FakeCarPropertyService
hardware/interfaces/automotive/vehicle/aidl/impl/fake_impl/FakeVehicleHardware
hardware/interfaces/automotive/vehicle/aidl/impl/default_config/config/默认 prop JSON 字典
hardware/interfaces/automotive/vehicle/aidl/impl/grpc/Android 16 GRPCVehicleHardware
device/google/cuttlefish/Cuttlefish 虚拟设备(见 04 篇)