11 - 调试与验证手段

本篇讲开发阶段如何无车调试信号功能:注入假信号、查配置、看日志、定位”信号不生效/收不到”。


1. 调试入口总览

目的工具命令
查信号配置(是否支持/取值范围)框架属性服务dumpsys micar_property
真实读写车端VHAL 直连dumpsys android.hardware.automotive.vehicle.IVehicle/micar --get/--set
注入假信号(模拟车端上报)VHAL 直连... --mock_from_car <PROP> -i <VAL> --stat 0
CarService 层注入car_servicedumpsys car_service publish-vhal-event
开 Mock 模式settingssettings put global mi_vehicle_mock_data 1
开调试日志settingssettings put global vehicle_debug_enable 1
看车端原始信号milogcatadb shell milogcat -s CARSIGNAL
按 propId 搜日志logcat`adb logcat

2. 查信号配置(是否支持)

框架属性层(推荐)——服务名 micar_property

adb shell dumpsys micar_property

子命令:

dumpsys micar_property list-vhal-props                    # 列全部约 3951 个 VehiclePropConfig
dumpsys micar_property get-carpropertyconfig <0xPROP>     # 查某信号的配置(access/changeMode/areaType/取值范围)
dumpsys micar_property get-property-value <0xPROP>        # 读当前值
dumpsys micar_property check-fake-vhal                    # 是否在 mock 模式
dumpsys micar_property get-vhal-backend                   # VHAL 后端类型

这一步能确认”这台车到底支不支持这个信号、支持到什么程度”。如果 get-carpropertyconfig 查不到,说明该机型不支持,UI 应隐藏。


3. VHAL 直连(真实读写车端 + 注入假信号)

服务名android.hardware.automotive.vehicle.IVehicle/micar(AIDL 平台,newton/yu7/海外)或 @2.0::IVehicle(HIDL 平台,Android 12/CN)。

判定平台:

adb shell service list | grep automotive.vehicle
# IVehicle(无版本号)= AIDL → 用 /micar
# @2.0::IVehicle = HIDL

调试三子命令(源码 MiVehicleClient.cpp:501-516,只支持这三个):

3.1 --get

adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/micar \
    --get 0x66403101
# 自动遍历所有 area

3.2 --set 真实下发

adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/micar \
    --set 0x65404101 -i 1 -a 1
# -i int 值;-i64 long;-f float;-s string;-b byte;-a area;-t 多值
# ⚠️ --set 会真实写入并下发车端

3.3 --mock_from_car 注入假上报(开发自测首选)

adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/micar \
    --mock_from_car 0x65404101 -i 1 -a 1 --stat 0
# 不真写源、只扇出给订阅者,模拟"车端上报"
# --stat 0/1/2 = AVAILABLE / UNAVAILABLE / ERROR

这是无车调试的核心:用 --mock_from_car 模拟车端上报,验证 App 的 onPropertyChanged 是否触发、UI 是否刷新。

已废弃命令(别用):--mock_set_enable--log_optional_enable--manager--rebuild_connection-h/--help(永远空输出)。


4. CarService 层注入

# 下行(模拟 App 下发)
adb shell dumpsys car_service publish-vhal-event <PROP> <AREA> <VALUE>
 
# 读值
adb shell dumpsys car_service get-property-value <PROP> <AREA>
 
# 注入(模拟车端上报到 CarService 层)
adb shell dumpsys car_service inject-vhal-event <PROP> <AREA> <VALUE>

⚠️ user 版限制cmd car_service 的 get/set 在 user 版会被 SecurityException 拦截(需 userdebug/eng)。VHAL dumpsys 不受限。


5. Mock 模式开关

# 开 Mock(开机默认关闭;8295 默认关,pad 默认开)
adb shell settings put global mi_vehicle_mock_data 1
 
# 开调试日志
adb shell settings put global vehicle_debug_enable 1

6. 日志定位

6.1 按 propId 搜日志(最有效)

propId 在日志里以 0x<hex> 或十进制出现。按 hex 搜能同时看到 VHAL 和 CarService 两层:

adb logcat | grep 0x65404101

6.2 关键 Tag

Tag内容
MiVehicleClientVHAL(C++)底层 get/set/mock
MiCarPropertyServiceCarServiceonPropertyChange: CarPropertyValue{...} / setProperty: CarPropertyValue{...}
PropServer-*MiCar 服务端mi_property 链路
PropSDK-*MiCar SDK 端MiCarPropertySDK 链路
VehicleControlManagerApp(项目)set 是否打印
CarPropertyCacheManagerApp(项目)上报是否到达、注册去重
SettingsCarPropertyEventCallbackApp(项目)信号回弹分发
CARSIGNAL车端原始adb shell milogcat -s CARSIGNAL

6.3 MiCarPropertyService 日志格式

MiCarPropertyService: onPropertyChange: CarPropertyValue{name=…, mPropertyId=…, mAreaId=…, mStatus=…, mTimestamp=…, mValue=…}
MiCarPropertyService: setProperty: CarPropertyValue{…}

6.4 项目内的常见警告(踩坑信号)

警告原因
"un-excepted observe propId"propId 没注册进 observedSet,onPropertyChanged 不回调(见 02 篇 §6.6
超时日志下发后超时未回弹,检查 VehiclePropertyConfig.sCustomTimeoutValue 阈值

7. status 枚举(小米扩展)

读日志时识别 status:

含义
0STATUS_AVAILABLE(可用)
1STATUS_UNAVAILABLE(不可用)
2STATUS_ERROR(错误)
4STATUS_TIMEOUT(小米新增)
5STATUS_TIMEOUT_UNAVAILABLE(小米新增)

原生 AAOS 把 timeout 和 unavailable 合并了,E4 起区分。判断可用必须 == 0,不要 != 1


8. 无车自检流程(端到端验证)

新写了一个信号功能,没车怎么验证?

1. 编译通过(dcd + xcd 两个 flavor)
   ./gradlew :app:assembleDcdDebug
   ./gradlew :app:assembleXcdDebug

2. 安装到设备/模拟器,进入目标页面

3. 确认 Controller 实例化
   adb logcat | grep <ControllerName>
   → 看到 onCreateInternal

4. 确认 CarService 连接
   adb logcat | grep onPropertyManagerPrepared
   → 看到 ready

5. 确认注册成功
   adb logcat | grep CarPropertyCacheManager
   → 看到 propId 注册

6. 注入假信号(模拟车端上报)
   adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/micar \
       --mock_from_car 0x<PROP> -i <VAL> --stat 0
   → 观察 UI 是否刷新到 VAL

7. 点击 UI(模拟用户下发)
   adb logcat | grep VehicleControlManager
   → 看到 set 打印
   → 如果有车端回弹,观察 CarPropertyCacheManager 是否收到

8. 验证超时回滚
   下发后不注入回弹,等超时
   → UI 应自动回退到上一态(restorePropertyToPrevious)

9. 常见问题诊断

9.1 信号收不到

排查方法
机型是否支持dumpsys micar_property get-carpropertyconfig 0x<PROP>
propId 是否在 observedSet"un-excepted observe propId" 警告
CarService 是否 readyonPropertyManagerPrepared
注册是否成功CarPropertyCacheManager
下行/上行 ID 是否一致检查 VehiclePropertyConfig.sTimeoutSignalMapping

9.2 下发不生效

排查方法
是否被超时回滚onSetPropertyTimeout
权限是否够user 版 cmd car_service 会被拦
车端是否真的收到milogcat -s CARSIGNAL
值是否合法对照 sSpecialSupportedPropValues 白名单

9.3 UI 闪烁/首帧错误

排查方法
是否吃了首帧缓存VehiclePermanentListener.getCachePropertyValue 是否返回初值
首次 get 是否做了getPropValueForFirstCache 兜底前提
多 Controller 互相干扰检查 areaId 过滤

10. 关键命令速查卡

# ===== 查配置 =====
adb shell dumpsys micar_property get-carpropertyconfig 0x<PROP>
 
# ===== 注入假信号(开发自测首选)=====
adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/micar \
    --mock_from_car 0x<PROP> -i <VAL> -a <AREA> --stat 0
 
# ===== 真实下发(慎用)=====
adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/micar \
    --set 0x<PROP> -i <VAL> -a <AREA>
 
# ===== 开 Mock / 日志 =====
adb shell settings put global mi_vehicle_mock_data 1
adb shell settings put global vehicle_debug_enable 1
 
# ===== 搜日志 =====
adb logcat | grep 0x<PROP>
adb shell milogcat -s CARSIGNAL
 
# ===== 判定平台 =====
adb shell service list | grep automotive.vehicle