01 - 痛点分析与现有调试手段
本篇是《信号调试工具》调研库的基石:先把”信号为什么不好模拟”拆解成可命名的子痛点,再盘点小米现有的调试/mock 手段(含一个被严重低估的应用层异常 mock 体系),最后指出 5 个盲区——后续各篇(02~08)的业界方案都是针对这些盲区的解药。
与 11-调试与验证手段 的关系:11 篇是项目内部命令手册(怎么敲 dumpsys/settings),本库聚焦业界方案对标 + 对抗选型 + 演进路线。两者互补,不重复。
1. 信号为什么”不好模拟”——10 个子痛点
把模糊的”信号不好调试”拆成 10 个可命名的子痛点,后续每个方案都标注它解决哪几个:
| # | 子痛点 | 表现 | 影响 |
|---|---|---|---|
| P1 | propId 难记 | 信号 ID 是 16 进制大整数(0x66403101=车门)或十进制(1715482881),要查 SOA Excel 反查,且表常滞后 | 命令易敲错、效率低 |
| P2 | areaId 语义复杂 | 1/4/16/64 在不同 zone 下语义不同,还易和 group 位(0x10000000/0x20000000)混淆 | 注入到错误 area,UI 不刷新 |
| P3 | 平台差异大 | 老 HIDL 用 lshal debug,新 AIDL 用 dumpsys;子命令行为不同(-i 多值 vs 单值) | 同一命令在新老平台表现不同,踩坑 |
| P4 | user 版被拦截 | cmd car_service 的 get/set 在 user 版被 SecurityException 拦 | 线上/user 版无法调试 |
| P5 | 命令冗长无 GUI | dumpsys 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-event | CarService 内部 HalService.onPropertyChange | 否(半路截胡) | 否 | CarService 及以上 |
--mock_from_car | VHAL 进程 dump() | 是 | 否 | VHAL 及以上 |
vc_client_mock | vehiclecore | 是 | 否 | vehiclecore 及以上 |
| 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 机制全貌
| 组件 | 路径 | 职责 |
|---|---|---|
VehicleControlMockEnv | app/src/main/java/com/android/car/settings/miauto/vehicle/VehicleControlMockEnv.java | 读 Settings.System 两个 key,注册 ContentObserver 实时刷新 |
VehiclePropertyUtil.refreshMockEnv(mask, propId) | base/settingsVehicleLib/.../vehicle/VehiclePropertyUtil.java:36 | 解析位掩码 → 3 个静态开关 |
SettingsCarPropertyManager.mockErrorEvent/mockTimeoutEvent | base/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 0ContentObserver 监听变化,改完立即生效,无需重启 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/ERROR | Error/Timeout/Unavailable + 小米扩展 Timeout |
| 验证链路深度 | VHAL→App 全链路 | 仅 App 回调层(VHAL→App 之间不验证) |
结论:两者互补。
- 测”App 收到异常后 UI 对不对”→ 用应用层 mock(门槛低、可节奏化)。
- 测”VHAL/CarService 到 App 的异常传递链路”→ 用
--mock_from_car --stat。 - 当前最大的问题是这套应用层 mock 没文档、没人用——本篇把它固化下来,应纳入团队 SOP。
3.6 局限(诚实评估)
- 只 mock 回调层,不 mock
getProperty同步读(同步读仍走真实 CarService)。 - Unavailable 是”一刀切”(
isPropertyMockUnavailable直接返回 false),不像 Error/Timeout 有节奏。 - 是全局静态开关(
sMockErrEnable等),多 Controller 并发时会互相干扰。 - 没有可视化(要敲 settings 命令),建议和 CarDemo 整合成 GUI。
4. 现有手段的 5 个盲区 → 对应调研方向
把 §2 的分层和 §1 的痛点对照,能清楚看到小米当前的空白地带:
| 盲区 | 缺什么 | 对应痛点 | 调研方向(后续篇章) |
|---|---|---|---|
| ❶ 信号源侧(CAN/DBC)无法注入 | 整条链路最底层缺模拟,vehiclecore 的 DBC 解析/映射测不到 | P7 | 03 CAN 开源生态 |
| ❷ 无离线/无车环境 | 没设备就停摆,CI 无法回归 | P7、P9 | 04 AAOS 模拟器 |
| ❸ 无录制+精确回放 | 路测 bug 无法在开发机复现 | P8 | 06 信号录制与回放 |
| ❹ DDS 第二通道无 mock | 充电曲线只能等真车充电 | P10 | 05 DDS 调试工具 |
| ❺ 应用层无自动化测试 | 信号逻辑不能 CI 回归 | P9 | 07 应用层测试框架 |
| + 官方能力没用足 | cmd car_service 按名字注入/错误码注入/驾驶态聚合都没用 | P1、P5、P6 | 02 AAOS 官方工具链 |
5. 一句话定位本库
小米现有的 VHAL/CarService 注入 + 应用层异常 mock,已经能覆盖日常 UI 调试; 真正的短板在信号源侧模拟、离线环境、录制回放、DDS mock、应用层 CI 测试这 5 个盲区,以及官方已有但没用足的能力(按名字注入等)。 本库后续 7 篇逐一给出业界方案 + 对抗选型 + 落地路线。