01 - 信号体系全景与术语
本篇是整个知识库的”地图”。讲清楚一件事:车辆信号从车端硬件,经过哪些层,最终到达 MiCarSettings 的 UI;以及沿途每一层的术语。
本篇的所有结论经多 agent 交叉验证 + 对抗核验(grep 定量 + 源码 import 实证),关键裁决见 08 篇。
1. 信号是什么
在车载语境里,“信号”(Signal)指车辆状态/控制的数据项。例如:
| 信号 | 类型 | 说明 |
|---|---|---|
| 车速 | STATE 上行 | 车 → App,连续变化 |
| 车门开关状态 | STATE 上行 | 车 → App |
| 车锁开关指令 | CMD 下行 | App → 车 |
| 空调温度设定 | 双向 | App 设 + 车回读 |
| 电池 SOC | STATE 上行 | 车 → App |
在 Android 侧,这些统称 CarProperty(车辆属性)。本项目里”信号”、“车控”、“车辆属性”、“CarProperty”是同义词。
2. 全链路总览(车端 ECU → App UI)
┌─────────────────────────────────────────────────────────────────┐
│ 车端 │
│ ECU ──CAN 总线(DBC 信号)──► MCU │
└─────────────────────────────────────────────────────────────────┘
│ SPI/GPIO/Ethernet
▼
┌─────────────────────────────────────────────────────────────────┐
│ SOC (QNX + Android) │
│ vehiclecore-service (MCU 桥) │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ vehicle@2.0-service (VHAL 进程) │ │
│ │ ├─ IVehicle/default (224 AOSP 标准) │ │
│ │ └─ IVehicle/micar (~3791 micar自定义)│ │
│ └─────────────────────────────────────────┘ │
│ │ IVehicle AIDL/HIDL │
│ ▼ │
│ CarService (Java, com.android.car) │
│ ── car-lib: CarPropertyManager ──► 给 App 用 │
└─────────────────────────────────────────────────────────────────┘
│ Binder (android.car)
▼
┌─────────────────────────────────────────────────────────────────┐
│ MiCarSettings App(本知识库的研究对象) │
│ │
│ ┌──── Manager 层(AOSP)────────────────────────────┐ │
│ │ LocalCarManager → Car.createCar │ │
│ │ → VehicleControlManager<CarPropertyManager> │ │
│ │ → CarPropertyCacheManager (去重缓存) │ │
│ │ → SettingsCarPropertyManager (业务封装) │ │
│ └────────────────────────────────────────────────────┘ │
│ │ 用到的 ID 来自 ↓ 用到的值类型来自 ↓ │
│ ┌──── propId 字典层(小米 mi.car.config + 桥接)────┐ │
│ │ mi.car.config.* (SOA 仓库发放的常量数值) │ │
│ │ MiCarPropertyIds (桥接类,settingsBaseLib) │ │
│ └────────────────────────────────────────────────────┘ │
│ ┌──── 值类型/框架层(小米 mi.car)──────────────────┐ │
│ │ mi.car.hardware.MiCarPropertyValue / MiVehicleArea│ │
│ │ mi.car:vehicle.support (maven, 车控支持 API) │ │
│ └────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──── UI 层(项目自研)─────────────────────────────┐ │
│ │ CarPropertyMgrPreferenceController (回调模式, 主流)│ │
│ │ CarPropertyRepo + UseCase + ViewModel (Flow 模式) │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
3. App 内的”三层架构”(核验后的真相)
⚠️ 这是本知识库最重要的结论之一,来自对抗核验(grep 定量 + 源码 import 实证)。前述探索 agent 把它笼统说成”用 AOSP CarPropertyManager”是不准确的——真实情况是三层混合。
| 层 | 来源 | 内容 | 项目里的类/依赖 |
|---|---|---|---|
| Manager 层 | AOSP android.car | 属性 get/set/register 的运行时 | android.car.hardware.property.CarPropertyManager(AOSP 新路径,6 文件直 import);项目自家 3 个包装类(SettingsCarPropertyManager、GlobalCarPropertyManager、CarPropertyManager);LocalCarManager 持有 AOSP android.car.Car |
| propId 字典层 | 小米 mi.car.config + 项目桥 | 信号 ID 常量及其数值 | mi.car.config.*(458 文件,752 import)提供真实数值;MiCarPropertyIds(settingsBaseLib)是桥接类,同时 import AOSP VehiclePropertyIds 和 mi.car.config.* |
| 值类型/框架层 | 小米 mi.car | 信号值对象、区域类型、车控框架 | mi.car.hardware.MiCarPropertyValue / MiVehicleAreaBody/Seat/Door(32 处使用);mi.car.core / mi.car.internal;maven mi.car:vehicle.support:0.11.56-test3(注释明写 “for vehicle property control”) |
为什么是三层混合?
- AOSP
CarPropertyManager只提供通用属性读写框架,不认识小米的车控语义 - 小米的车控信号体系(约 3791 个自定义 prop)需要自己的字典(
mi.car.config)和值类型(mi.car.hardware) - 项目用
MiCarPropertyIds把小米字典桥接成项目内统一 ID 表,再通过 AOSP Manager 读写
依赖实证(base/settingsBaseLib/build.gradle):
api 'mi.car:vehicle.support:0.11.56-test3' // 小米车控支持 SDK
api 'mi.car:core.api:0.1.2.48'
api 'mi.car:sdk.static:6.5.1.13'
api 'com.mi.car.config:api:0.0.15-SNAPSHOT' // propId 字典
api 'mi.car:sdk.dynamic:0.2.4.67'AOSP 侧则是 compileOnly 的 android.car_*.jar(设备框架提供)。
这个三层结构正是整机”A17+ 迁移到
mi.car.MiCarPropertyManager”的前提:目前 Manager 层挂 AOSP,迁移会令 Manager 层也改走 mi.car。详见 08 篇。
4. 信号在车端的定义(三层源头)
本节来自整机《车控信号》资料,理解它有助于”找到一个信号怎么用”。
4.1 三层数据源(权威性由高到低)
| 源 | 内容 | 维护方 |
|---|---|---|
| DBC | CAN 总线信号原始定义(SignalName 如 SteerWhlHeatFcnSts) | ECU/网关 |
| SOA 服务接口表 MS11 | 整车权威信号矩阵(飞书 sheets) | 信号管理系统 https://preview.operation.iccc.mioffice.cn/#/signal/soa |
| 代码生成 | SOA Excel → soa_parser.py → AIDL/HIDL/常量 | 自动 |
mi.car.config.* 常量就是从 SOA 表生成的,所以项目不维护 propId 数值,由 SOA 仓库统一发放。
4.2 一个车控设备通常涉及三个信号
| 信号类型 | 含义 | 示例 |
|---|---|---|
| 状态信号(Sts) | 当前值 | SteerWhlHeatFcnSts |
| 使能信号(AvlSts) | 是否可用(与状态信号同 propId,通过 status 字段) | SteerWhlHeatFcnAvlSts |
| 异常信号(NotAvlRsn) | 不可用原因(独立 propId) | SteerWhlHeatFcnNotAvlRsn(0-5 枚举) |
项目里对应:主信号走 getPropertyIdSet(),异常信号作为依赖信号走 getObservedPropertyIdSet() + needMapReceiveDependProperty(见 03 篇 §8)。
5. propId 的 32 位位布局
来自整机《Mi AAOS 信号体系实现》。理解位布局能帮你读日志、判断信号归属。
propId 是 32 位 int:
| bit | 31-28 | 27-24 | 23-16 | 15-0 |
|---|---|---|---|---|
| 含义 | Group | Area | Type | unique id |
| AAOS 取值 | SYSTEM=0x1 / VENDOR=0x2 | GLOBAL/WINDOW/MIRROR/SEAT/DOOR/WHEEL/BODY | STRING/BOOLEAN/INT32/…/FLOAT/BYTES/MIXED | 0x0000-0xffff |
| MiCar 取值 | MICAR=0x6 | A0/A1/A2(MiVehicleZone) | 同上 | 同上 |
小米新增了 MICAR=0x60000000 这个 group(标准 AAOS 只有 SYSTEM=0x1 和 VENDOR=0x2)。
判断一个 prop 是否走小米自定义链路:看 group 位(bit 31-28)是否 = 0x6。
示例:
0x61407207(group=6=MICAR)=BASIC_INFO_POWER_MODE整车电源模式0x66403101= 1715482881 =DOOR_STATE0x11400200(group=1=SYSTEM)= AOSP 标准信号
6. 关键数据载体
6.1 CarPropertyValue(AOSP)
字段:propertyId / areaId / value / status / timestamp
timestamp=SystemClock#elapsedRealtimeNanos()(开机纳秒时间,不是世界时间)- status 取值(小米扩展):
- 原生:
STATUS_AVAILABLE(0) / STATUS_UNAVAILABLE(1) / STATUS_ERROR(2) - 小米新增:
STATUS_TIMEOUT(4) / STATUS_TIMEOUT_UNAVAILABLE(5)
- 原生:
⚠️ 判断可用性必须用
getStatus() == STATUS_AVAILABLE,不要用getStatus() != STATUS_UNAVAILABLE(后者在小米新增 status 下会误判)。
6.2 小米值类型(mi.car.hardware)
mi.car.hardware.MiCarPropertyValue // 小米版值对象(比 AOSP 多 relative/extension 字段)
mi.car.hardware.MiVehicleAreaBody/Seat/Door // 小米版区域类型
SOA 的 Payload 比标准 AAOS 多了 relative 和 extension 两个字段,这是小米扩展。
6.3 项目内的数据类
| 类 | 路径 | 作用 |
|---|---|---|
VehicleData | base/settingsVehicleLib/.../vehicle/VehicleData.kt | data class VehicleData(propId, propVal, areaId, isSync),写信号包装 |
CarPropertyData<T> | base/settingsVehicleLib/.../vehicle/CarPropertyRepo.kt:194 | Flow 模式的 UI 状态载体(value/isEnabled/errorCode) |
CarModelData | base/settingsBaseUi/.../common/livedata/CarModelData.kt | 车模图刷新 LiveData |
7. 术语对照表
| 术语 | 含义 | 出现层 |
|---|---|---|
| Signal / SignalName | 车端 CAN 信号名(DBC 定义) | ECU/CAN |
| Property / CarProperty / VehicleProperty | Android 侧的车辆属性抽象 | CarService/App |
| PropertyId (propId) | 32 位 int,唯一标识一个属性 | 全链路 |
| SignalId | 车端信号 ID(CAN/DBC 侧) | 车端 |
| MiVehicleProperty | 小米自定义的 prop 枚举(group=MICAR),约 3791 条 | micar 链路 |
| AreaId / areaId | 区域 ID,与 propId 共同确定一个具体物件(如主驾位温度);0 = 全局 | 全链路 |
| MiVehicleZone | 小米对 Area 的扩展(A0/A1/A2 位段) | micar 链路 |
| CarPropertyValue / MiCarPropertyValue | 属性值封装(含 value/status/timestamp) | App |
| CarPropertyConfig | 属性元数据(access/changeMode/areaType/取值范围) | App |
| 上行信号 | get / 上报(车 → App) | 项目注释 |
| 下行信号 | set / 下发(App → 车) | 项目注释 |
| 中间态信号 | 有过渡态的信号(如车窗升降中) | 项目注释 |
| 依赖信号 | 影响控制项 enable/loading 但不影响值的关联信号 | 项目注释 |
| UI 先行 | 写信号前先更新本地缓存/Flow 让 UI 立即响应 | 项目注释 |
8. App 如何拿到 Car 实例(铁律)
来自整机《Create Car ANR 警告》。MiCarSettings 必须遵守。
铁律:用 Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT(值=0)异步初始化,在 onLifecycleChanged 回调里拿 Manager。严禁传大固定值(如 5000ms)冒充”同步但又不超时”——CarService 启动慢时仍会 ANR。
项目里的实现:LocalCarManager(见 02 篇)用 Car.createCar(ctx, null, CAR_WAIT_TIMEOUT_WAIT_FOREVER, listener)(项目封装为”永远等”,但在独立线程,不 block 主线程)。
9. 异常处理(易踩坑)
AOSP getIntProperty/getFloatProperty 等会抛 RuntimeException(IDE 不强制处理,极易被忽略):
CarInternalErrorExceptionPropertyAccessDeniedSecurityExceptionPropertyNotAvailableExceptionPropertyNotAvailableAndRetryExceptionIllegalStateException/IllegalArgumentException
推荐写法:
try {
value = cpm.getIntProperty(propId, areaId);
} catch (CarInternalErrorException | PropertyNotAvailableAndRetryException
| PropertyNotAvailableException e1) {
value = -1; // 信号 timeout 或硬件故障
} catch (PropertyAccessDeniedSecurityException | IllegalArgumentException e2) {
value = -1; // 权限或调用错误
}项目里的做法:业务侧不直接调 AOSP Manager,而是走
SettingsCarPropertyManager,它内部已做 try-catch + 缓存 + 超时兜底。业务侧只调getIntProperty/setCarProperty。详见 02 篇。