01 - 信号体系全景与术语

本篇是整个知识库的”地图”。讲清楚一件事:车辆信号从车端硬件,经过哪些层,最终到达 MiCarSettings 的 UI;以及沿途每一层的术语。

本篇的所有结论经多 agent 交叉验证 + 对抗核验(grep 定量 + 源码 import 实证),关键裁决见 08 篇


1. 信号是什么

在车载语境里,“信号”(Signal)指车辆状态/控制的数据项。例如:

信号类型说明
车速STATE 上行车 → App,连续变化
车门开关状态STATE 上行车 → App
车锁开关指令CMD 下行App → 车
空调温度设定双向App 设 + 车回读
电池 SOCSTATE 上行车 → 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 个包装类(SettingsCarPropertyManagerGlobalCarPropertyManagerCarPropertyManager);LocalCarManager 持有 AOSP android.car.Car
propId 字典层小米 mi.car.config + 项目桥信号 ID 常量及其数值mi.car.config.*(458 文件,752 import)提供真实数值;MiCarPropertyIdssettingsBaseLib)是桥接类,同时 import AOSP VehiclePropertyIdsmi.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 三层数据源(权威性由高到低)

内容维护方
DBCCAN 总线信号原始定义(SignalName 如 SteerWhlHeatFcnStsECU/网关
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:

bit31-2827-2423-1615-0
含义GroupAreaTypeunique id
AAOS 取值SYSTEM=0x1 / VENDOR=0x2GLOBAL/WINDOW/MIRROR/SEAT/DOOR/WHEEL/BODYSTRING/BOOLEAN/INT32/…/FLOAT/BYTES/MIXED0x0000-0xffff
MiCar 取值MICAR=0x6A0/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_STATE
  • 0x11400200(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 多了 relativeextension 两个字段,这是小米扩展。

6.3 项目内的数据类

路径作用
VehicleDatabase/settingsVehicleLib/.../vehicle/VehicleData.ktdata class VehicleData(propId, propVal, areaId, isSync),写信号包装
CarPropertyData<T>base/settingsVehicleLib/.../vehicle/CarPropertyRepo.kt:194Flow 模式的 UI 状态载体(value/isEnabled/errorCode)
CarModelDatabase/settingsBaseUi/.../common/livedata/CarModelData.kt车模图刷新 LiveData

7. 术语对照表

术语含义出现层
Signal / SignalName车端 CAN 信号名(DBC 定义)ECU/CAN
Property / CarProperty / VehiclePropertyAndroid 侧的车辆属性抽象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 不强制处理,极易被忽略):

  • CarInternalErrorException
  • PropertyAccessDeniedSecurityException
  • PropertyNotAvailableException
  • PropertyNotAvailableAndRetryException
  • IllegalStateException / 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 篇


10. 阅读建议

  • 想看 App 内主通道怎么封装 → 02 篇
  • 想看 UI 怎么响应信号 → 03 篇 / 04 篇
  • 想看信号字典怎么用 → 06 篇
  • 想知道为什么不用 mi.car SDK / 未来怎么演进 → 08 篇
  • 要新增一个信号功能 → 09 篇