10 - 平台差异(dcd / xcd / global)

本篇讲 MiCarSettings 如何用一份源码适配三个 flavor(dcd / xcd / global),以及信号层如何屏蔽不同车型/芯片平台(8295 vs 其它、HIDL vs AIDL)的差异。


1. 三个 Flavor

Flavor含义典型平台
dcdDCD 平台8295 芯片(“堆叠显示”架构)
xcdXCD 平台其它主流车型
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.gradleconstants.gradle 定义两套 jar 路径:

用途dcdxcd
车控业务 jardcd_javalib_watt_250721.jarxcd_javalib_1129.jar
android.car jarandroid.car_watt0911.jarxcd_android.car_1129.jar

2.3 关键约束(写代码必须遵守)

  1. settingsVehicleLib只用符号常量MiCarPropertyIds.XxxCtrl.YYYmi.car.config.Driving.ZZZ),不写魔法数字
  2. 不写 if (flavor == dcd) 这类运行时判断
  3. 新增 propId 时确认两套 jar 都有对应常量(否则另一平台编译失败)
  4. 真正有平台差异的业务逻辑,写到对应模块的 src/dcddifsrc/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 版HIDLandroid.hardware.automotive.vehicle@2.0::IVehicle
yu7 / newton / 海外AIDLandroid.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/default224 个 AOSP 标准 prop标准 CarService(GAS 兼容)
IVehicle/micar约 3791 个 micar 自定义 propMiVehicleService / 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含义
SYSTEM0x10000000AOSP 标准信号
VENDOR0x20000000厂商扩展(AOSP 预留)
MICAR0x60000000小米自定义信号(标准 AAOS 没有,小米新增)

判断一个 prop 是否走小米自定义链路,看 group 位即可。例如:

  • 0x61407207(group=6=MICAR)= BASIC_INFO_POWER_MODE 整车电源模式
  • 0x66403101 = DOOR_STATE(1715482881 十进制)
  • 0x11400200(group=1=SYSTEM)= AOSP 标准信号

详见整机《Mi AAOS 信号体系实现》的 propId 位布局章节。


8. 给开发者的建议

  1. 公共模块(settingsVehicleLib)只用符号常量,平台差异靠 jar 切换 + 子类化
  2. 新增 propId:确认 com.mi.car.config:api 已升级,且 dcd/xcd 两套 jar 都有
  3. 平台专属业务:写到 src/dcddif / src/xcddif,子类覆盖
  4. 海外差异:写到 app/src/region/global
  5. 不要在运行时判断 flavor 来切信号逻辑——这是反模式,应该用子类化
  6. 调试时注意 VHAL 协议:AIDL 平台用 IVehicle/micar,HIDL 平台用 @2.0::IVehicle

9. 关键路径速查

主题路径
flavor 声明base/settingsVehicleLib/build.gradle
jar 注入逻辑build.gradletasks.withType(JavaCompile)
jar 路径定义dependencies.gradleconstants.gradle
平台专属源码app/src/dcddifapp/src/xcddifapp/src/region/{cn,global}
8295 判断MiCarSettings.is8295Architecture()