10 - 平台差异(dcd / xcd / global)
本篇讲 MiCarSettings 如何用一份源码适配三个 flavor(
dcd/xcd/global),以及信号层如何屏蔽不同车型/芯片平台(8295 vs 其它、HIDL vs AIDL)的差异。
1. 三个 Flavor
| Flavor | 含义 | 典型平台 |
|---|---|---|
dcd | DCD 平台 | 8295 芯片(“堆叠显示”架构) |
xcd | XCD 平台 | 其它主流车型 |
global | 海外 | 海外车型 + 国际化 |
2. 核心机制:编译期切换 framework.jar(一份源码)
2.1 settingsVehicleLib 的 flavor 声明
base/settingsVehicleLib/build.gradle:10
productFlavors {
dcd {}
xcd {}
global {}
}并配 sourceSets,但 src/dcddif / src/xcddif 目录实际为空——也就是说,settingsVehicleLib 层面是一份源码编三套平台,差异不在源码,而在依赖的 jar。
2.2 jar 注入
根 build.gradle:113(参考 docs/05-车辆接口层与IPC.md)在 tasks.withType(JavaCompile) 里按 currentFlavor 把对应 jar 注入 bootstrapClasspath。
dependencies.gradle 和 constants.gradle 定义两套 jar 路径:
| 用途 | dcd | xcd |
|---|---|---|
| 车控业务 jar | dcd_javalib_watt_250721.jar | xcd_javalib_1129.jar |
| android.car jar | android.car_watt0911.jar | xcd_android.car_1129.jar |
2.3 关键约束(写代码必须遵守)
settingsVehicleLib里只用符号常量(MiCarPropertyIds.XxxCtrl.YYY、mi.car.config.Driving.ZZZ),不写魔法数字- 不写
if (flavor == dcd)这类运行时判断 - 新增 propId 时确认两套 jar 都有对应常量(否则另一平台编译失败)
- 真正有平台差异的业务逻辑,写到对应模块的
src/dcddif或src/xcddif里,通过子类化覆盖基类行为,而不是在公共代码里分支
⚠️ propId 数值在不同平台不同:dcd / xcd 两套 jar 里,
MiCarPropertyIds同名常量的真实数值可能不同,但源码字面量一致(都引用mi.car.config.Xxx.YYY)。这正是”用符号常量不用数字”的原因。
3. 平台特有源码的位置
真正有差异的源码(非空)在:
app/src/dcddif/ # dcd 专属
app/src/xcddif/ # xcd 专属
app/src/region/cn/ # 国行
app/src/region/global/ # 海外
部分 settingsPage 模块也有:
settingsPage/settingsSystem/src/dcddif、src/xcddif
settingsPage/micarConnectionSettings/src/...
settingsPage/micarChargeSettings/src/dcddif # 如 EnergyChargeCurveActivity(仅 dcd)
4. RTI 通道的 8295 门控
05 篇 已述:RTI DDS 仅在 8295(DCD)平台启用:
// ChargingReportRepo.kt:83
if (MiCarSettings.is8295Architecture()) {
// 走 RTI Connext DDS
} else {
// 走 AIDL(ChargingReportMgr.registerListener)
}这是项目里少有的运行时平台判断,因为 RTI 库只在 8295 平台预置。
5. 整机层:HIDL vs AIDL(VHAL 传输协议)
本节来自整机《车控信号》资料,属于”App 之下”的差异,但理解它有助于调试。
VHAL 服务名因平台而异:
| 平台 | VHAL 协议 | 服务名 |
|---|---|---|
| Android 12 / CN 版 | HIDL | android.hardware.automotive.vehicle@2.0::IVehicle |
| yu7 / newton / 海外 | AIDL | android.hardware.automotive.vehicle.IVehicle |
判定命令:
adb shell service list | grep automotive.vehicle
# IVehicle(无版本号)= AIDL
# @2.0::IVehicle = HIDL对应配置:device/micar/common/vendor/vendor_common.mk:9-28
这种差异对 MiCarSettings 透明——因为 App 通过 AOSP
CarPropertyManager访问,CarService 内部适配 HIDL/AIDL。
6. 整机层:VHAL 双实例(newton 等 AIDL 平台)
AIDL 平台上 VHAL 注册两个实例(来源:整机《Newton VHAL 架构与调试入口》):
| 实例 | 内容 | 喂给谁 |
|---|---|---|
IVehicle/default | 224 个 AOSP 标准 prop | 标准 CarService(GAS 兼容) |
IVehicle/micar | 约 3791 个 micar 自定义 prop | MiVehicleService / support-lib |
车控调试都用 /micar 实例:
adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/micar --get <PROP>详见 11 调试篇。
7. propId 的 group 位:识别 micar 自定义 vs AOSP 标准
propId 是 32 位 int,bit 31-28 是 group:
| group | 值 | 含义 |
|---|---|---|
SYSTEM | 0x10000000 | AOSP 标准信号 |
VENDOR | 0x20000000 | 厂商扩展(AOSP 预留) |
MICAR | 0x60000000 | 小米自定义信号(标准 AAOS 没有,小米新增) |
判断一个 prop 是否走小米自定义链路,看 group 位即可。例如:
0x61407207(group=6=MICAR)=BASIC_INFO_POWER_MODE整车电源模式0x66403101=DOOR_STATE(1715482881 十进制)0x11400200(group=1=SYSTEM)= AOSP 标准信号
详见整机《Mi AAOS 信号体系实现》的 propId 位布局章节。
8. 给开发者的建议
- 公共模块(settingsVehicleLib)只用符号常量,平台差异靠 jar 切换 + 子类化
- 新增 propId:确认
com.mi.car.config:api已升级,且 dcd/xcd 两套 jar 都有 - 平台专属业务:写到
src/dcddif/src/xcddif,子类覆盖 - 海外差异:写到
app/src/region/global - 不要在运行时判断 flavor 来切信号逻辑——这是反模式,应该用子类化
- 调试时注意 VHAL 协议:AIDL 平台用
IVehicle/micar,HIDL 平台用@2.0::IVehicle
9. 关键路径速查
| 主题 | 路径 |
|---|---|
| flavor 声明 | base/settingsVehicleLib/build.gradle |
| jar 注入逻辑 | 根 build.gradle(tasks.withType(JavaCompile)) |
| jar 路径定义 | dependencies.gradle、constants.gradle |
| 平台专属源码 | app/src/dcddif、app/src/xcddif、app/src/region/{cn,global} |
| 8295 判断 | MiCarSettings.is8295Architecture() |