第2章:Android Automotive系统架构概览

好,咱们直接进入正题。这一章我会带你从宏观上理解AAOS的整体架构。说白了,就是先看看这栋楼长什么样,每层是干嘛的,然后再聊聊它和普通Android到底有啥不一样。

2.1 AOSP源码结构:这堆代码怎么摆的?

我第一次接触AOSP源码时,说实话有点懵。几万个文件夹,上百G的代码,从哪看起?后来我总结出一个习惯——先看顶层目录结构。

AOSP的根目录大概长这样:

.
├── art/          # Android Runtime,就是ART虚拟机
├── bionic/       # C库,底层基础
├── bootable/     # 启动引导相关
├── build/        # 编译系统,makefile全在这
├── cts/          # 兼容性测试套件
├── dalvik/       # 老版虚拟机(现在基本被ART取代)
├── developers/   # 开发者文档
├── development/  # 开发工具和示例
├── device/       # 设备相关配置,厂商定制主要在这
├── external/     # 第三方开源库
├── frameworks/   # 核心框架,Java层主力
├── hardware/     # 硬件抽象层HAL
├── kernel/       # Linux内核
├── packages/     # 系统应用
├── system/       # 系统服务
├── vendor/       # 厂商私有代码
└── Makefile      # 入口

嗯,这里我要特别强调两个目录:device/vendor/。做AAOS移植时,你大部分时间都在跟这两个目录打交道。我当年第一次做车载移植,就是在device/下新建了一个厂商目录,然后折腾了整整两周才把系统跑起来。

2.2 AAOS与AOSP的区别:到底改了啥?

很多人问我:AAOS不就是AOSP加几个车载应用吗?

其实没那么简单。我列个表,你一看就明白:

对比项 AOSP AAOS
用户界面 手机/平板UI 车载专用UI(大屏、分屏、旋钮)
音频架构 普通AudioFlinger CarAudioService + 多区音频
电源管理 手机休眠/唤醒 车辆电源状态(ACC/IGN/CRANK)
网络连接 WiFi/蜂窝 车载以太网 + CAN总线
硬件抽象 标准HAL Vehicle HAL + 扩展HAL
系统服务 标准服务 CarService + 车辆属性服务
安全模型 应用沙箱 车辆功能权限 + 驾驶安全约束

你看,这可不是简单的换皮。AAOS在AOSP基础上,增加了整整一层车载专属的架构。我举个例子——音频。在手机上,音频输出就是扬声器或耳机。但在车上呢?你可能需要:

  • 导航语音从驾驶位喇叭出
  • 音乐从全车喇叭出
  • 电话从蓝牙耳机出
  • 后排乘客看视频从后排喇叭出

这就是多区音频。AOSP根本处理不了这种场景,AAOS专门做了CarAudioService来搞定。

核心结论:AAOS = AOSP + 车载框架层 + 车辆硬件抽象层 + 车载应用层。这三层缺一不可。

2.3 核心服务组件介绍:谁在背后干活?

AAOS里跑着一堆服务,但真正核心的就那么几个。我挑最重要的说:

2.3.1 CarService

这是AAOS的心脏。所有车载功能都通过它来调度。它运行在系统进程中,负责:

  • 管理车辆属性(车速、车门、空调等)
  • 协调音频焦点(导航优先于音乐)
  • 处理驾驶模式(停车时可看视频,行驶中禁用)
  • 管理车辆网络(以太网、CAN)

我记得有一次,客户反馈说空调控制没反应。查了半天,发现是CarService启动时没拿到Vehicle HAL的代理。说白了就是服务连不上硬件层,自然控制不了空调。

2.3.2 Vehicle HAL

这是连接Android系统和车辆硬件的桥梁。它定义了一套标准接口,让上层服务可以读写车辆属性。

典型的Vehicle HAL接口长这样:

// 车辆属性定义
#define VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET 0x1234

// HAL接口
status_t VehicleHal::setProperty(
    VehiclePropValue* propValue) {
    // 写入CAN总线或LIN总线
    // 控制空调温度
    return sendToCanBus(propValue);
}

嗯,这里要注意:Vehicle HAL是厂商必须实现的。不同车型的空调控制逻辑完全不同,但接口必须统一。这就是HAL存在的意义——隔离变化。

2.3.3 CarAudioService

前面提到了多区音频,这个服务就是干这个的。它管理:

  • 音频设备映射(哪个App走哪个喇叭)
  • 音量分组(导航音量、媒体音量、电话音量分开调)
  • 音频焦点策略(紧急广播时自动降低音乐音量)

避坑指南:我曾经遇到一个bug,导航语音和音乐同时播放时,导航声音特别小。查了两天才发现,是CarAudioService的音频焦点策略配置错了。默认的焦点策略是「后进先出」,但导航应该用「独占+混音」模式。这个配置在/vendor/etc/car_audio_configuration.xml里改。

2.3.4 CarPowerManagementService

车载电源管理和手机完全不同。手机只有「亮屏/灭屏/关机」三种状态。但车辆有:

  • ACC(附件通电,收音机可用)
  • IGN(点火,全车通电)
  • CRANK(启动瞬间,大功率设备断电)
  • SLEEP(休眠,保留内存)
  • SHUTDOWN(完全断电)

这个服务负责在这些状态间切换,同时通知其他App和Service做相应处理。比如,进入CRANK状态时,屏幕要瞬间黑一下,但系统不能崩溃。

2.3.5 CarProjectionService

这个你可能不熟,但它很重要。它负责手机投屏功能——就是CarPlay和Android Auto的底层支持。它管理:

  • 投屏协议(USB、WiFi)
  • 屏幕映射(手机屏幕投射到车机屏幕)
  • 交互转发(触摸事件从车机传到手机)

说实话,这个服务我调过最头疼。不同手机厂商的投屏协议实现有差异,经常出现「iPhone能连,小米不能连」的情况。后来我学乖了,先在device/目录下加了一堆兼容性补丁。

2.4 架构分层总结

好了,咱们把这一章的内容串起来。AAOS的架构从上到下大概是:

  1. 应用层:车载Launcher、设置、空调控制等App
  2. 框架层:CarService、CarAudioService等核心服务
  3. 硬件抽象层:Vehicle HAL、Audio HAL等
  4. 内核层:Linux内核 + 车载驱动(CAN、以太网)
  5. 硬件层:车机SoC、显示屏、音响、CAN总线等

每一层都有明确的职责和接口。做移植时,你主要改的是第3层和第4层。框架层基本不动,除非你要加新功能。

重要提醒:千万别试图绕过HAL直接操作硬件。我见过有人为了省事,在App里直接读写CAN总线。结果系统升级后,硬件接口变了,App直接崩溃。遵守分层设计,后面维护会轻松很多。

下一章,我们会深入Vehicle HAL,看看怎么实现一个真正的车载属性。到时候我会拿空调控制做例子,一步步带你写代码。