01 - 痛点分析与现有调试手段

本篇是《信号调试工具》调研库的基石:先把”信号为什么不好模拟”拆解成可命名的子痛点,再盘点小米现有的调试/mock 手段(含一个被严重低估的应用层异常 mock 体系),最后指出 5 个盲区——后续各篇(02~08)的业界方案都是针对这些盲区的解药。

11-调试与验证手段 的关系:11 篇是项目内部命令手册(怎么敲 dumpsys/settings),本库聚焦业界方案对标 + 对抗选型 + 演进路线。两者互补,不重复。


1. 信号为什么”不好模拟”——10 个子痛点

把模糊的”信号不好调试”拆成 10 个可命名的子痛点,后续每个方案都标注它解决哪几个:

#子痛点表现影响
P1propId 难记信号 ID 是 16 进制大整数(0x66403101=车门)或十进制(1715482881),要查 SOA Excel 反查,且表常滞后命令易敲错、效率低
P2areaId 语义复杂1/4/16/64 在不同 zone 下语义不同,还易和 group 位(0x10000000/0x20000000)混淆注入到错误 area,UI 不刷新
P3平台差异大老 HIDL 用 lshal debug,新 AIDL 用 dumpsys;子命令行为不同(-i 多值 vs 单值)同一命令在新老平台表现不同,踩坑
P4user 版被拦截cmd car_service 的 get/set 在 user 版被 SecurityException线上/user 版无法调试
P5命令冗长无 GUIdumpsys android.hardware.automotive.vehicle.IVehicle/micar --mock_from_car 0x61407207 -i 1 -a 0 --stat 0新人上手难、易错
P6异常状态难模拟UNAVAILABLE/TIMEOUT/ERROR 三态、以及小米扩展的 STATUS_TIMEOUT(4)/TIMEOUT_UNAVAILABLE(5) 难触发异常分支 UI 测不到
P7难脱离真车强依赖真车/实机 CarService,开发者没设备就跑不通信号链路等车成本高、CI 无法回归
P8回放能力弱现有 LogPropMonitor.py 只能按 log 顺序回放,无精确时间戳、无场景编排、无可视化路测 bug 难复现
P9应用层难自动化测试Controller/封装层强依赖 CarService,无车不能单测改一处全靠手测、回归成本高
P10第二通道(DDS)无注入入口充电曲线走 RTI DDS,dumpsys 不可达,无 mock 命令充电链路只能等真车充电

这 10 个痛点是后续所有方案选型的标尺。一张表读懂本库:每个工具写明”解决 P几”。


2. 现有调试/mock 手段分层全景

小米已经有相当完整的调试体系,分 7 层(自上而下注入点越深、验证范围越广):

┌─────────────────────────────────────────────────────────────┐
│ ⑦ 车端信号源(MCU/CAN/QNX)                                  │  ← 目前空白(见 03 CAN 篇)
├─────────────────────────────────────────────────────────────┤
│ ⑥ vehiclecore-service(MCU 枢纽)  vc_client_mock             │
├─────────────────────────────────────────────────────────────┤
│ ⑤ VHAL 进程(AIDL IVehicle/micar)                            │
│    dumpsys ... --get / --set / --mock_from_car --stat 0/1/2   │  ← 主力(11 篇详述)
├─────────────────────────────────────────────────────────────┤
│ ④ CarService(Java)                                          │
│    dumpsys car_service inject-vhal-event / publish-vhal-event │
│    cmd car_service inject-error-event / emulate-driving-state │  ← 02 AAOS 篇发现:官方更多子命令没用
├─────────────────────────────────────────────────────────────┤
│ ③ 应用层异常 mock(项目独有,被低估 ⭐)                        │
│    Settings.System[mock_vehicle_property_env / _id]           │  ← 本文 §3 详解
├─────────────────────────────────────────────────────────────┤
│ ② 整车 Mock 开关 + 脚本编排                                   │
│    settings put global vehicle_mock_data 1                    │
│    scripts/mock_light_scenarios.sh(灯光场景自动轮播)          │
├─────────────────────────────────────────────────────────────┤
│ ① 辅助 APP + 日志                                             │
│    CarDemo4Test.apk(GUI 点 Mock)/ milogcat -s CARSIGNAL      │
└─────────────────────────────────────────────────────────────┘

关键认知(决定每个工具能测什么)

注入层注入点是否过真实 VHAL binder是否写底层硬件验证范围
inject-vhal-eventCarService 内部 HalService.onPropertyChange(半路截胡)CarService 及以上
--mock_from_carVHAL 进程 dump()VHAL 及以上
vc_client_mockvehiclecorevehiclecore 及以上
CAN 注入(待建)MCU/CAN否(虚拟)全链路(含 DBC 解析)

即:注入点越深,验证的链路越长。调试 App UI 用 --mock_from_car 够;要验证 vehiclecore 的信号解析/映射逻辑,得下沉到 CAN 层(见 03 CAN 篇)。


3. ⭐ 被严重低估的能力:项目内置的「应用层异常 mock 体系」

这是本次调研最重要的内部发现:小米已经在 app/ 里实现了一套应用层、无需 root、可指定 propId、运行时动态切换的信号异常 mock 体系,但外部知识库(《车辆信号调试 Q&A》《信号接入指北 3.0》)和项目 11-调试与验证手段 都没记录它。它正是 P6(异常状态难模拟)的现成解药。

3.1 机制全貌

组件路径职责
VehicleControlMockEnvapp/src/main/java/com/android/car/settings/miauto/vehicle/VehicleControlMockEnv.javaSettings.System 两个 key,注册 ContentObserver 实时刷新
VehiclePropertyUtil.refreshMockEnv(mask, propId)base/settingsVehicleLib/.../vehicle/VehiclePropertyUtil.java:36解析位掩码 → 3 个静态开关
SettingsCarPropertyManager.mockErrorEvent/mockTimeoutEventbase/settingsVehicleLib/.../vehicle/SettingsCarPropertyManager.kt:616,635在信号回调里拦截,伪造 Error/Timeout

3.2 位掩码语义(mock_vehicle_property_env

bit0 (0x1) = MOCK_PROPERTY_ERR_MASK        → 模拟信号 Error
bit1 (0x2) = MOCK_PROPERTY_TIMEOUT_MASK     → 模拟信号 Timeout
bit2 (0x4) = MOCK_PROPERTY_UNAVAILABLE_MASK → 模拟信号 Unavailable
可组合:0x6 = Timeout + Unavailable 同时模拟

配套 mock_vehicle_property_id:指定 mock 哪个 prop(16 进制字符串如 0x66403101),-1 表示 mock 所有信号

3.3 触发命令(无需 root、无需 userdebug、运行时生效)

# 模拟车门信号(0x66403101) Unavailable
adb shell settings put system mock_vehicle_property_id 0x66403101
adb shell settings put system mock_vehicle_property_env 4
 
# 模拟所有信号 Error + Timeout(组合掩码 0x3)
adb shell settings put system mock_vehicle_property_id -1
adb shell settings put system mock_vehicle_property_env 3
 
# 关闭
adb shell settings put system mock_vehicle_property_env 0

ContentObserver 监听变化,改完立即生效,无需重启 App

3.4 触发节奏(源码 VehiclePropertyUtil.java:144-163

为避免一上来就全 mock 导致页面崩溃,机制内置了节奏控制:

// 第 5 次之后、每隔一次触发(counter > 5 && counter % 2 == 0)
boolean mockWork = sMockErrEnable && mockErrCounter > MOCK_WAIT_TIME && mockErrCounter % 2 == 0;

即:正常上报 5 次后,才开始间歇性注入异常——模拟真实场景下”偶发故障”。

3.5 对比 VHAL 层 --mock_from_car --stat(P6 的两套解药)

维度VHAL --mock_from_car --stat 0/1/2应用层 mock_vehicle_property_env
注入层VHAL 进程App 内 SettingsCarPropertyEventCallback
需要 root是(dumpsys)(settings put)
user 版可用dumpsys 可用可用
指定 propId每次 command 带settings key 设一次,持续生效
节奏控制无(每次手动)(5 次后间歇)
模拟范围AVAILABLE/UNAVAILABLE/ERRORError/Timeout/Unavailable + 小米扩展 Timeout
验证链路深度VHAL→App 全链路仅 App 回调层(VHAL→App 之间不验证)

结论:两者互补

  • 测”App 收到异常后 UI 对不对”→ 用应用层 mock(门槛低、可节奏化)。
  • 测”VHAL/CarService 到 App 的异常传递链路”→ 用 --mock_from_car --stat
  • 当前最大的问题是这套应用层 mock 没文档、没人用——本篇把它固化下来,应纳入团队 SOP。

3.6 局限(诚实评估)

  1. 只 mock 回调层,不 mock getProperty 同步读(同步读仍走真实 CarService)。
  2. Unavailable 是”一刀切”(isPropertyMockUnavailable 直接返回 false),不像 Error/Timeout 有节奏。
  3. 是全局静态开关(sMockErrEnable 等),多 Controller 并发时会互相干扰。
  4. 没有可视化(要敲 settings 命令),建议和 CarDemo 整合成 GUI。

4. 现有手段的 5 个盲区 → 对应调研方向

把 §2 的分层和 §1 的痛点对照,能清楚看到小米当前的空白地带

盲区缺什么对应痛点调研方向(后续篇章)
❶ 信号源侧(CAN/DBC)无法注入整条链路最底层缺模拟,vehiclecore 的 DBC 解析/映射测不到P703 CAN 开源生态
❷ 无离线/无车环境没设备就停摆,CI 无法回归P7、P904 AAOS 模拟器
❸ 无录制+精确回放路测 bug 无法在开发机复现P806 信号录制与回放
❹ DDS 第二通道无 mock充电曲线只能等真车充电P1005 DDS 调试工具
❺ 应用层无自动化测试信号逻辑不能 CI 回归P907 应用层测试框架
+ 官方能力没用足cmd car_service 按名字注入/错误码注入/驾驶态聚合都没用P1、P5、P602 AAOS 官方工具链

5. 一句话定位本库

小米现有的 VHAL/CarService 注入 + 应用层异常 mock,已经能覆盖日常 UI 调试; 真正的短板在信号源侧模拟、离线环境、录制回放、DDS mock、应用层 CI 测试这 5 个盲区,以及官方已有但没用足的能力(按名字注入等)。 本库后续 7 篇逐一给出业界方案 + 对抗选型 + 落地路线。