3. Android Automotive OS 架构总览

做车载开发,第一件事就是搞明白系统长什么样。Android Automotive 不是凭空冒出来的,它底层还是 Android,但为了跑在车上,Google 和芯片厂做了大量改造。

我个人习惯把整个系统想象成一栋楼。从地基到顶层,每一层各司其职。你想想看,如果不懂分层,遇到问题就像无头苍蝇——明明是个底层驱动 bug,你却在应用层调了一整天。

3.1 四层架构总览

Android Automotive 从上到下分为四层:

  • 应用层 — 用户直接看到的界面,比如地图、音乐、设置
  • 框架层 — 系统核心服务,管理窗口、应用生命周期、车辆属性
  • 硬件抽象层 (HAL) — 连接系统和硬件的桥梁,屏蔽芯片差异
  • 内核层 — 真正的硬件驱动,Linux 内核 + 车载专用驱动

每一层只跟相邻层通信。这样做的好处是——换芯片不用改应用,换应用不用动驱动。

核心原则:分层架构的本质是解耦。我在项目中见过太多「跨层调用」的骚操作,最后都成了维护噩梦。记住:上层不直接碰硬件,下层不关心 UI。

Android Automotive 四层架构 应用层 (Application Layer) 地图 | 音乐 | 设置 | 电话 | 第三方车载应用 框架层 (Framework Layer) CarService | Vehicle HAL 接口 | 窗口管理 | 权限管理 ActivityManager | PackageManager | 车载专用 API 硬件抽象层 (HAL) Vehicle HAL | Audio HAL | Camera HAL | Sensor HAL 内核层 (Kernel Layer) Linux Kernel | CAN 驱动 | GPIO | I2C | 电源管理

3.2 应用层 — 用户看到的一切

应用层就是用户在中控屏上点来点去的东西。但车载应用跟手机应用有个本质区别——安全优先。

举个例子,手机上的地图 App 可以随便切后台,但车载地图在驾驶中必须一直显示。这就是为什么 Automotive 有专门的 CarApp 组件。

我的经验:刚开始做车载应用开发时,我习惯用手机那套思维写代码。结果发现车载系统对「分屏」「多窗口」「驾驶模式」有严格限制。后来我总结了一条铁律:车载应用先问「安全吗」,再问「好用吗」。

应用层主要包含:

  • 系统预装应用(设置、电话、媒体)
  • 第三方车载应用(通过 Car App Library 开发)
  • 仪表盘 / HUD 相关界面

3.3 框架层 — 系统的「大脑」

框架层是 Android Automotive 最核心的部分。它管理着所有应用的运行,同时提供车载特有的服务。

这里有个关键角色——CarService。它是车载系统的总管,所有跟车相关的操作都要经过它。

服务名称 职责 我遇到的坑
CarService 管理车辆属性、驾驶模式、车辆状态 属性读写没加同步锁,导致多应用同时读车速时崩溃
Vehicle HAL 接口 定义车辆属性和控制命令的标准接口 接口版本不匹配,HAL 返回的数据格式跟框架层预期不一致
窗口管理 处理多屏幕、分屏、安全区域 没考虑屏幕安全区,导航栏被系统状态栏遮挡
权限管理 控制哪些应用可以访问车辆数据 第三方应用申请读取车速权限,审核没通过

注意:框架层是系统稳定性的关键。我曾经在项目中遇到一个问题——CarService 启动顺序依赖了某个第三方库,结果库初始化失败,整个系统卡在开机动画。从那以后,我坚持核心服务不依赖外部库。

3.4 硬件抽象层 (HAL) — 芯片厂的「翻译官」

HAL 层的作用说白了就是——让上层不用关心底层用什么芯片。

不同的车厂用不同的芯片:高通、瑞萨、恩智浦、TI……每个芯片的寄存器、中断、DMA 都不一样。如果没有 HAL,框架层得为每款芯片写一套代码,那工作量想想就可怕。

Android Automotive 定义了标准的 Vehicle HAL 接口:

// Vehicle HAL 核心接口示例
interface IVehicle {
    // 获取车辆属性(如车速、电量)
    Status getProperty(VehiclePropId propId, out VehiclePropValue value);
    
    // 设置车辆属性(如空调温度、车窗位置)
    Status setProperty(VehiclePropId propId, VehiclePropValue value);
    
    // 订阅属性变化(如车速变化时通知应用)
    Status subscribe(VehiclePropId propId, float sampleRate);
    
    // 释放订阅
    Status unsubscribe(VehiclePropId propId);
}

芯片厂只需要实现这套接口,上层就能无缝工作。这就是 HAL 的价值。

关键点:HAL 是 C/C++ 实现的,运行在独立的进程里。框架层通过 Binder IPC 跟 HAL 通信。这样做的好处是——即使 HAL 崩溃,框架层也不会挂掉。

3.5 内核层 — 真正的「硬核」

内核层是 Linux Kernel 加上车载专用驱动。这是离硬件最近的一层,也是问题最多的一层。

车载系统对内核有特殊要求:

  • 实时性:刹车信号、安全气囊触发必须在毫秒级响应
  • 稳定性:不能死机,不能蓝屏,不能无故重启
  • 安全性:内核态不能被用户态程序随意访问

常见的车载内核驱动包括:

  • CAN 驱动:读取车辆总线数据(车速、转速、故障码)
  • GPIO 驱动:控制物理按键、指示灯
  • I2C/SPI 驱动:连接传感器、触摸屏、音频芯片
  • 电源管理驱动:处理休眠、唤醒、低功耗模式

避坑指南:我曾经在项目里遇到一个诡异问题——车子熄火后系统无法唤醒。查了三天,最后发现是内核的电源管理驱动里,某个 GPIO 的中断触发条件写错了。所以做内核开发,示波器是你的好朋友。

3.6 层间通信机制

各层之间怎么通信?我整理了一张表:

通信方向 技术手段 特点
应用层 ↔ 框架层 Binder IPC 高效、安全、支持跨进程调用
框架层 ↔ HAL HIDL / AIDL 标准化接口,支持多厂商实现
HAL ↔ 内核层 系统调用 / ioctl 直接操作硬件,性能最高
内核层 ↔ 硬件 寄存器读写 / DMA 最底层,依赖芯片手册

你可能会问:为什么不用共享内存?嗯,共享内存虽然快,但安全性差。车载系统对安全要求极高,Binder 的权限校验机制是必须的。

3.7 小结

Android Automotive 的四层架构,每一层都有明确的职责边界。应用层管界面,框架层管逻辑,HAL 层管适配,内核层管硬件。

我个人觉得,理解分层架构是车载开发的第一道门槛。跨过这道门槛,后面学什么都会顺很多。记住一句话:别跨层,别越权,各司其职。