06 - 信号字典与命名约定

本篇解决”信号叫什么、在哪定义、怎么 grep、怎么新增一个信号常量”的问题。这是开发者最常用的一篇。


1. 信号的标识方式

1.1 主通道(CarProperty)—— int 常量

信号 ID 是 int 常量,全部定义在一个超大”信号字典”文件里:

base/settingsBaseLib/src/main/java/com/android/car/settings/miauto/vehicle/MiCarPropertyIds.java

⚠️ 重要纠正:既有文档 docs/05-车辆接口层与IPC.md 说这个文件在 settingsVehicleLib这是错的。物理位置在 settingsBaseLib(多 agent 源码确认)。但包名是 com.android.car.settings.miauto.vehicle,引用方式是 import com.android.car.settings.miauto.vehicle.MiCarPropertyIds——物理模块和包名不一致,是个历史遗留,注意别被误导。

文件规模:2140 行,约 30 个内部静态类

1.2 组织方式:按功能分组成嵌套类

每个信号是 public static final int值来自外部依赖 mi.car.config.*(不是手写数字):

public class MiCarPropertyIds {
    public static class LightCtrl {
        public static final int HEADLIGHT = Light.EXTERIOR_LIGHT_MODE;
        public static final int FOG = Light.REAR_FOG_LIGHT_STATE;
        public static final int MOOD_LIGHT_BRIGHTNESS = ...;
    }
    public static class LockCtrl {
        public static final int WALK_AWAY_LOCK = ...;
        public static final int LOCK_BEEP = ...;
    }
    // ... 约 30 个内部类
}

1.3 内部类(功能域)清单

内部类典型信号
LightCtrl灯光HEADLIGHTFOGMOOD_LIGHT_BRIGHTNESS
DoorCtrl车门/前备箱/充电口COVER_STATECHARGE_PORTCENTRAL_LOCK
LockCtrl锁车WALK_AWAY_LOCKCHILDREN_LOCKLOCK_BEEP
DrivingCtrl驾驶控制(最大类)STEERING_MODEEPBSUSPENSION_HEIGHTGEAR、能量回收
BattleCtrl赛道模式轮胎/刹车/电池温度、G 值表
AutoPilot智驾AEBNOA_CONTROLRCTADOWLCA
EnergyManagement充电/能量CHARGE_CONTROLBATTERY_SOCCHARGE_STATUSTRANSFER_POWER
SeatAdjustControl座椅靠背/前后/高度调节、位置记忆
SafeAndSecurity安防哨兵 SENTRY_MAIN_SWITCH、DMS、行车记录仪、限速
WindowCtrl车窗/遮阳帘/调光天幕
MirrorControl后视镜
HvacCtrl空调
CarConfig配置字(车型配置位)TRANSMISSION_DRIVELINESUSPENSION_CONFIG
Condition状态/能耗统计WHEEL_PRESSURETOTAL_MILEAGE
Hud / Radar / CaliperHUD/雷达/卡钳
Service雨刮等WIPER_RAIN_SENSOR_DETECT_LEVEL
BodyCtrl车身
Intercom对讲

2. ⚠️ 关键认识:propId 的真实数值不在本项目

项目内部不维护 propId 的数值。数值由外部 maven 依赖统一发放:

base/settingsBaseLib/build.gradle:118

api 'com.mi.car.config:api:0.0.15-SNAPSHOT'

这个 com.mi.car.config:api(即 SOA 仓库)提供这些命名空间(全部为 public static final int):

mi.car.config.Body / Door / Driving / Energy / Guard / Hvac / Light /
Mirror / Peripheral / Seat / Warning / Window / CommonParams

以及枚举子类(如 Door.ChargePortStateDriving.OffRoadSubModeStatusBody.SuspensionHeight)。

因此”新增一个信号”的真实步骤

  1. 升级 com.mi.car.config:api 版本(联系车控/SOA 团队)
  2. MiCarPropertyIds.java 的对应内部类里加一行:public static final int XXX = mi.car.config.YourDomain.YOUR_SIGNAL;
  3. 确认 dcd / xcd 两套 framework jar 都包含该常量

2.5 ⚠️ mi.car 不只是字典(对抗核验补充)

早期探索 agent 笼统说”mi.car 只是 propId 字典”——不准确。经 grep 定量核验,mi.car 在项目里承担三类角色:

mi.car 子包角色命中规模
mi.car.config.*propId 字典(常量数值)458 文件,752 import
mi.car.hardware.*值类型MiCarPropertyValueMiVehicleAreaBody/Seat/Door32 处使用
mi.car.core.* / mi.car.internal.*框架基础设施(storage、activity、user 等)56 + 30 import

而且 base/settingsBaseLib/build.gradle 显式声明了车控 SDK maven 依赖:

api 'mi.car:vehicle.support:0.11.56-test3'   // 注释: "micar-support-api for vehicle property control"
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'

注意区分:mi.car.config(字典)是编译期常量mi.car.hardware.MiCarPropertyValue(值类型)是运行时数据对象,比 AOSP CarPropertyValuerelative/extension 字段(SOA 扩展)。MiCarPropertyIds.java 本身就是 AOSP↔mi.car 的桥接类(同时 import android.car.VehiclePropertyIdsmi.car.config.*)。

完整的三层架构图见 01 篇 §3


3. grep 关键词表(带命中量)

命中量在 find ... -name "*.java" -o -name "*.kt" 范围、已排除 build/ 下统计。

3.1 最有效的 3 个关键词

关键词命中文件数用途
MiCarPropertyIds379找到所有信号使用点(首选)
SettingsCarPropertyManager83找到所有读写入口
CarPropertyMgrPreferenceController54找到所有车控 UI 控件

3.2 完整关键词表

关键词命中文件数含义
Property595通用属性
CarProperty517CarProperty 相关
prop458propId / getProperty / setProperty
VehicleProperty238VehiclePropertyUtil / VehiclePropertyConfig 等
GlobalCarPropertyManager34全局单例入口
carProperty47多为字段名 mCarPropertyManager
RTI78rtiLib + 充电曲线(详见 05 篇
Signal / signal59 / 38多在 rtiLib + 中文注释”信号”
RTISignal7RTI 信号
VehicleControlManager8底层封装(业务一般不直接用)

3.3 ⚠️ 不存在的命名(别 grep)

以下命名在项目里命中为 0,是其它车载项目的命名习惯,本项目不用

getSignal / setSignal / subscribeSignal / notifySignal
onSignalChanged / SignalListener / SignalCallback
VehicleSignal / SignalManager

本项目的”信号”就是 CarProperty,读写分别叫 getXxxProperty / setCarProperty,监听叫 registerPropertyCallback,回调叫 onPropertyChanged / onHandlePropertyChange

3.4 推荐入门 grep 组合

# 找一个业务模块订阅了哪些信号
grep -rn "getPropertyIdSet\|getObservedPropertyIdSet" settingsPage/<module>/src
 
# 找一个 propId 在哪些地方被读写
grep -rn "MiCarPropertyIds.LightCtrl.FOG" --include=*.kt --include=*.java
 
# 找 Flow 架构相关
grep -rn "mapPropFlow\|collectIn\|CarPropertyRepo" settingsPage/
 
# 找超时/回退/中间态处理
grep -rn "onSetPropertyTimeout\|CarPropertyTimeoutFlag\|needIntermediateState"

4. 中文术语对照(读注释必备)

中文含义
信号 / 车控 / 车辆属性 / 车控信号同义,指 vehicle property
上行信号get / 上报(车 → App)
下行信号set / 下发(App → 车)
信号上报 / 信号下发 / 订阅信号描述收发动作
信号频率sample rate(configPropertyRate
中间态信号有过渡态的信号(如车窗升降中),对应 CarPropertyTimeoutFlag.RESTARTneedIntermediateState
依赖信号影响控制项 enable/loading 但不影响值的关联信号(needMapReceiveDependPropertygetSubDependPropertyId
保留信号值当前车型暂不支持的预留值,UI 保持上一态(isValidPropValshouldUpdateUIByPropVal
UI 先行写信号前先更新本地缓存/Flow 让 UI 立即响应(CarPropertyRepo.setCarPropertyneedEmit=true
下行信号与上行信号不一致下发 id 与回读 id 不同,用 obtainSetPropertyId 处理
组合 areaId / 多 area同一 propId 不同区域(左/右座椅、左/右童锁),用 areaId 区分

5. 信号 ↔ UI 控件的数据驱动映射

5.1 页面级信号集合:*PropertysMap.java

每个业务页面有一个 Map 文件,声明该页关心的所有信号 ID。grep 命中 10 个:

文件模块
settingsPage/micarLightSettings/.../LightsVehiclePropertysMap.java灯光
settingsPage/micarLockSettings/.../DoorVehiclePropertysMap.java车门
settingsPage/micarLockSettings/.../LockVehiclePropertysMap.java锁车
settingsPage/micarLockSettings/.../ElectricReleaseHeadGatePropertysMap.java电释放前备箱
settingsPage/micarSafetyServiceSettings/.../SafetyServiceVehiclePropertysMap.java安防
settingsPage/micarDrivingSettings/.../DrivingVehiclePropertyMap.java驾驶
settingsPage/micarDisplaySettings/.../DisplayVehiclePropertysMap.java + display/DisplayPropertyMap.kt显示
settingsPage/VehicleBodyControl/.../VehicleBodyPropertysMap.java + vehicle/VehicleBodyPropertyMap.kt车身

典型样子(LightsVehiclePropertysMap.java:12):

public static ArraySet<Integer> sExteriorLightPropertyIds = new ArraySet<>(
    Arrays.asList(new Integer[]{
        MiCarPropertyIds.LightCtrl.HEADLIGHT,
        MiCarPropertyIds.LightCtrl.FOG
    }));

5.2 快捷控制项工厂:VehicleQuickCtrl

DoorVehiclePropertysMap.java 里展示了信号→图标→文案→Tab 标识→点击监听一条龙声明的快捷控制项:

return new VehicleQuickCtrl<Integer>(
        Door.POWER_OPERATED_DOOR_MOVING_STATUS, VehicleAreaDoor.DOOR_ROW_1_LEFT,
        R.drawable.micar_ic_driver_door, R.string.lock_door_driver_door_open) {
}.withDefault(CommonParams.OnOff.OFF)
 .applyKeyGenStrategy(VehicleQuickCtrl.KEY_STRATEGY_PROPERTY_AND_AREA)
 .withTabFlag(TAB_FLAG_DRIVER_DOOR)
 .withAllowClickWhenDisabled(true)
 .withOnClickListener(listener);

5.3 信号值范围注解:@PropertyRange

base/settingsVehicleLib/src/main/java/com/android/micar/settings/annotation/PropertyRange.java

@Retention(RUNTIME) @Target(ElementType.TYPE)
public @interface PropertyRange {
    int lower() default 0;
    int upper() default 0;
    int defaultVal() default -1;
    int offset() default 0;
    int stepValueForVoiceAssist() default 1;
}

6. 信号的横切配置:VehiclePropertyConfig

⚠️ 注意包名:com.android.micar.settings.carproperty(与 vehicle/ 目录下其它类的包名 com.android.car.settings.miauto.vehicle 不同,历史遗留)。

路径:base/settingsVehicleLib/src/main/java/com/android/micar/settings/carproperty/VehiclePropertyConfig.java

static {} 块维护 4 张表

类型作用
sSpecialSupportedPropValuesMap<Integer, List<Integer>>某信号支持的合法 value 白名单
sValuesShouldBeCachedSet哪些 value 应该缓存
sCustomTimeoutValueMap<String, Long>每个信号下发后的超时时长
sTimeoutSignalMappingMap<Integer, Integer>下行信号 → 上行信号映射(下发 ID 和上报 ID 不一致时,如 EnergyManagement.AC_CHARGING_CURRENT_MAX → ALL_CURRENT_STATUS

这 4 张表是处理”边界信号”的核心,新增信号功能时如遇下行/上行 ID 不一致、超时阈值异常,优先来这里配置。


7. 关键路径速查

你想做的事看这里
找一个信号叫什么base/settingsBaseLib/.../vehicle/MiCarPropertyIds.java
找信号的数字值mi.car.config.*(外部 jar,IDE 可跳转)
新增信号常量MiCarPropertyIds.java 对应内部类加一行
找某信号的读写者grep -rn "MiCarPropertyIds.Xxx.YYY"
找超时/缓存配置base/settingsVehicleLib/.../carproperty/VehiclePropertyConfig.java
找页面关心的信号集合settingsPage/<module>/.../*PropertysMap.java
找读写 APISettingsCarPropertyManager.ktgetXxxProperty / setCarProperty
找 UI 控件基类CarPropertyMgrPreferenceController.java
找全局读信号GlobalCarPropertyManager.kt
找 RTI(大数据流)settingsCommon/rtiLib/.../rtilib/RTISignalMgr.java + 业务侧 RTISignalConstants.java