第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的架构从上到下大概是:
- 应用层:车载Launcher、设置、空调控制等App
- 框架层:CarService、CarAudioService等核心服务
- 硬件抽象层:Vehicle HAL、Audio HAL等
- 内核层:Linux内核 + 车载驱动(CAN、以太网)
- 硬件层:车机SoC、显示屏、音响、CAN总线等
每一层都有明确的职责和接口。做移植时,你主要改的是第3层和第4层。框架层基本不动,除非你要加新功能。
重要提醒:千万别试图绕过HAL直接操作硬件。我见过有人为了省事,在App里直接读写CAN总线。结果系统升级后,硬件接口变了,App直接崩溃。遵守分层设计,后面维护会轻松很多。
下一章,我们会深入Vehicle HAL,看看怎么实现一个真正的车载属性。到时候我会拿空调控制做例子,一步步带你写代码。