3. AAOS系统架构与R-Car适配层
Android Automotive OS(AAOS)并不是把手机 Android 直接搬到车机上,而是在 AOSP 之上叠加了一整套面向车辆的总线抽象、服务框架与应用接口。R-Car 平台要跑通 AAOS,关键不在于“能不能点亮屏幕”,而在于从 Bootloader 到 CarService 的每一层是否与 R-Car 的硬件资源、BSP 驱动、HAL 接口正确对齐。本节按启动链自下而上梳理这条适配路径。
一、Android 系统启动链与 R-Car 的介入点
AAOS 的启动链可以概括为:BootROM → Bootloader(R-Car 上通常是 U-Boot 或厂商定制 SPL)→ Linux Kernel → init → 各类 native 服务 → Zygote → SystemServer → CarService → CarApp。R-Car 的适配工作几乎贯穿整条链,但介入方式各不相同。
Bootloader 阶段主要完成 DRAM 初始化、加载内核与设备树(DTB)。R-Car H3/M3/E3 等 SoC 的 DTB 中会描述 CPU 集群、GIC、SCIF/HSCIF 串口、I2C、GPIO、PCIe、显示控制器(DU)、视频输出等节点。内核启动后,init 依据 init.rc 与 init.<hardware>.rc 拉起服务。R-Car 平台通常需要新增或修改 init.rc 中的 import 项,把 BSP 提供的 init.rc 片段纳入启动流程,例如提前挂载 /vendor、启动 android.hardware.automotive.vehicle@2.0-service 等。
Zygote 启动后 fork 出 SystemServer,SystemServer 中会依次启动 ActivityManagerService、WindowManagerService、PackageManagerService 等,随后通过 SystemServiceManager 启动 CarServiceHelperService,由它绑定并拉起 CarService。CarService 再通过 VHAL 与车辆总线通信,最终把车辆信号暴露给 CarApp。这条链上任何一环的 SELinux 策略、权限、HAL 接口版本不匹配,都会导致 CarService 起不来或车辆属性读不到。
二、HAL 与 VHAL:车辆信号的抽象边界
AAOS 中与车辆相关的 HAL 主要是 Vehicle HAL(VHAL)。它定义在 hardware/interfaces/automotive/vehicle/ 下,当前主流版本为 android.hardware.automotive.vehicle@2.0 或 @2.1。VHAL 的核心职责是把车辆总线上的物理信号抽象为 VehicleProperty,并提供 get、set、subscribe 三类操作。
R-Car 适配 VHAL 时,通常不会从零实现,而是基于 AOSP 的 VehicleHal 默认实现或芯片厂商提供的参考实现,替换其中的信号采集与下发部分。例如,车速信号可能来自 CAN 总线,空调温度来自 LIN 或私有总线,车门状态来自 GPIO。适配层需要把这些来源统一映射到 VHAL 的属性 ID 上。
一个典型的属性映射示例如下:
VehicleProperty::PERF_VEHICLE_SPEED -> CAN ID 0x1A0, 字节 0-1, 系数 0.01, 单位 km/h
VehicleProperty::HVAC_TEMPERATURE_SET -> LIN 帧 0x22, 字节 2, 系数 0.5, 单位 ℃
VehicleProperty::DOOR_OPEN -> GPIO 12, 高电平表示开门
VehicleProperty::GEAR_SELECTION -> CAN ID 0x2B0, 字节 3, 枚举值 P/R/N/D
映射完成后,VHAL 服务需要以 android.hardware.automotive.vehicle@2.0-service 的形式注册到 hwservicemanager。CarService 启动时会通过 IVehicle::getService() 获取该服务,并建立订阅关系。如果 VHAL 服务没有注册成功,CarService 会在日志中报 Unable to get IVehicle,车辆属性全部不可用。
三、CarService 与 CarApp 框架
CarService 是 AAOS 中车辆功能的中枢。它内部包含 CarPropertyService、CarPowerManagementService、CarAudioService、CarPackageManagerService 等子服务。CarPropertyService 负责把 VHAL 的 VehicleProperty 封装为 CarPropertyManager 接口,供应用层调用。
应用层通过 CarPropertyManager 读写车辆属性,典型调用如下:
CarPropertyManager mgr = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE);
// 读取车速
CarPropertyValue<Float> speed = mgr.getProperty(Float.class, VehiclePropertyIds.PERF_VEHICLE_SPEED, 0);
// 订阅车速变化
mgr.registerCallback(callback, VehiclePropertyIds.PERF_VEHICLE_SPEED, CarPropertyManager.SENSOR_RATE_ONCHANGE);
CarApp 框架则规定了车机应用的形态:CarAppService、CarActivity、CarLauncher 等。与手机应用不同,车机应用需要声明 android.car.permission.CAR_* 权限,并在 AndroidManifest.xml 中声明 android.software.car.templates_host 等特性。R-Car 平台上,CarApp 的显示输出依赖 DU 控制器与 SurfaceFlinger 的合成路径,如果显示时序配置错误,应用可能正常启动但画面无法输出。
四、R-Car BSP 与内核适配要点
R-Car BSP 通常以 Yocto 层的形式提供,包含内核补丁、设备树、U-Boot、驱动模块和固件。适配 AAOS 时,需要重点关注以下几点:
- 设备树节点:确认 DU、VSP、I2C、GPIO、PCIe、以太网等节点与硬件原理图一致,尤其是显示输出接口(LVDS、HDMI、DP)的时序参数。
- 内核配置:打开
CONFIG_DRM_RCAR_DU、CONFIG_I2C_RCAR、CONFIG_GPIO_RCAR、CONFIG_CAN_RCAR等选项,并确保 Android 所需的CONFIG_ANDROID_BINDER_IPC、CONFIG_ASHMEM已启用。 - init.rc 与 SELinux:把 BSP 的
init.rc片段导入 Android 启动流程,并为 VHAL 服务、CAN 设备节点、GPIO 节点编写正确的 SELinux 策略,避免avc: denied。 - 分区与镜像:确认
boot、vendor、system、product分区大小与镜像格式匹配,R-Car 上常用 eMMC 或 UFS,需在分区表中预留足够空间。
dmesg 中的内核报错、logcat 中的 CarService 日志、以及 dumpsys car_service 输出的车辆属性状态。三者结合可以快速定位是驱动层、HAL 层还是框架层的问题。整体来看,AAOS 在 R-Car 上的适配是一条从 Bootloader 到 CarApp 的纵向链路,每一层都有明确的接口与检查点。理解这条链路的层次关系与数据流向,比记住某个具体命令更重要——它决定了遇到问题时应该先看哪一层、再查哪一层。