2. Android Automotive 平台架构:AAOS 系统架构概览、核心服务与 HAL 层、车载应用框架
好,咱们进入正题。这一章我打算聊聊 Android Automotive 的底层骨架。说白了,就是 AAOS 到底是怎么搭起来的。很多做上层应用的朋友,可能一辈子都不用碰 HAL 层,但理解了这个架构,你写代码时心里会更有底。
我个人习惯把 AAOS 的架构想象成一栋楼。地基是 Linux 内核,往上盖的是 HAL 层,再往上就是各种核心服务,最顶层才是咱们开发者接触最多的应用框架。嗯,咱们一层层来看。
2.1 AAOS 系统架构概览
先看一张宏观图(当然,这里没有图,我用文字给你画出来)。AAOS 的架构其实和手机上的 Android 很像,但针对车载场景做了大量定制。
它主要分这么几层:
- 应用层:你写的那些车载应用,比如音乐、导航、设置,都在这一层。
- 应用框架层:这是 Google 提供的一套 API,帮你管理界面、生命周期、资源等等。
- 系统服务层:这是 AAOS 的核心。像 CarService、VehicleService 这些大管家,都住在这里。
- HAL 层:硬件抽象层。它把底层的硬件差异给屏蔽了。你想想看,不同车厂的空调、车窗、方向盘按键,接口千奇百怪,但到了 HAL 层,都变成了统一的接口。
- Linux 内核层:最底层,负责和硬件打交道,比如驱动、内存管理、进程调度。
我在项目中遇到过一个问题:有个第三方应用直接去读底层的 CAN 总线数据,结果系统直接崩溃了。为什么?因为它绕过了 HAL 层,没有权限控制。所以,千万别想着跳过 HAL 层直接操作硬件,这是大忌。
2.2 核心服务与 HAL 层
这一节是重点。AAOS 的核心服务,说白了就是几个关键的进程,它们一直在后台跑着,管理着车辆的一切。
2.2.1 CarService
CarService 是车载系统的总管家。它负责管理车辆的状态,比如车门、车窗、空调、座椅等等。它通过 Vehicle HAL 和底层硬件通信。
它的工作流程大概是这样的:
- 应用调用 CarService 的 API,比如“打开空调”。
- CarService 把这个请求转给 Vehicle HAL。
- Vehicle HAL 通过 CAN 总线或者别的协议,告诉空调控制器“该干活了”。
- 空调控制器执行操作,然后返回状态。
- 状态再原路返回给应用。
你看,这一来一回,CarService 起到了承上启下的作用。它不直接操作硬件,但它是所有车载功能的入口。
2.2.2 Vehicle HAL
Vehicle HAL 是硬件抽象层。它的核心接口是 IVehicle。这个接口定义了你能够对车辆做哪些操作,比如获取车速、控制车窗、读取方向盘角度等等。
每个车厂都需要实现自己的 Vehicle HAL。为什么?因为不同车厂的硬件不一样。有的车用 CAN 总线,有的车用 LIN 总线,还有的用以太网。Vehicle HAL 就是把这些差异都封装起来。
我建议你在实现 Vehicle HAL 时,注意以下几点:
- 属性定义要清晰:每个车辆属性(比如车速、油量)都要有唯一的 ID 和类型。
- 错误处理要完善:硬件可能会出问题,比如传感器坏了。你的 HAL 要能优雅地处理这些错误,而不是直接崩溃。
- 性能要达标:有些属性,比如车速,需要高频更新。你的 HAL 实现要能扛得住。
2.2.3 其他核心服务
除了 CarService,还有几个重要的服务:
- UserManagerService:管理用户账户。咱们这门课的主题,就是围绕它展开的。
- AudioService:管理音频焦点。车载音频很复杂,导航、电话、音乐、提示音,它们之间不能打架。
- PowerService:管理电源。车载系统的电源管理比手机复杂得多,涉及到休眠、唤醒、ACC 信号等等。
2.3 车载应用框架
应用框架,就是咱们开发者直接打交道的那一层。AAOS 在标准 Android 框架的基础上,增加了一些车载专用的组件。
2.3.1 Car API
Car API 是 Google 提供的一套接口,让应用能够访问车辆数据。比如,你想知道当前车速,可以调用 Car.getCarInfoManager().getVehicleSpeed()。
这些 API 都是通过 CarService 来间接访问硬件的。所以,你的应用不需要关心底层是 CAN 还是 LIN,只需要调用 API 就行了。
举个例子,获取车辆信息的代码大概长这样:
// 获取 Car 实例
Car car = Car.createCar(context);
// 获取车辆信息管理器
CarInfoManager infoManager = (CarInfoManager) car.getCarManager(Car.INFO_SERVICE);
// 获取车速
float speed = infoManager.getVehicleSpeed();
// 获取油量
float fuelLevel = infoManager.getFuelLevel();
你看,代码很简单。但要注意,这些 API 可能不是实时更新的。有些属性,比如车速,是高频更新的;有些属性,比如油量,是低频更新的。你的应用要根据实际情况来处理。
2.3.2 车载 UI 组件
AAOS 还提供了一些车载专用的 UI 组件。比如:
- CarUiRecyclerView:针对车载触摸屏优化的列表控件。
- CarDrawerLayout:侧滑菜单,适合在驾驶场景下快速切换功能。
- CarToolbar:顶部的工具栏,通常包含返回按钮、标题和操作按钮。
这些组件都考虑了驾驶安全。比如,按钮的尺寸更大,触摸区域更宽,防止误触。我建议你在开发车载应用时,尽量使用这些组件,而不是自己从头造轮子。
2.3.3 多用户与多显示
车载系统的一个特点是多用户和多显示。一辆车可能有好几个屏幕:中控屏、仪表盘、副驾屏、后排屏。每个屏幕可能属于不同的用户。
AAOS 的应用框架支持这种场景。每个用户都有自己的应用栈和设置。比如,驾驶员登录后,中控屏显示导航;副驾登录后,副驾屏显示视频。
这里有个坑:不同屏幕之间的应用状态管理。我曾经遇到过一个情况:驾驶员在中控屏上打开了音乐应用,然后副驾在副驾屏上也打开了同一个音乐应用。结果两个屏幕上的播放状态不一致,音乐一会播放一会暂停。后来我们通过为每个用户分配独立的进程,才解决了这个问题。
嗯,这一章的内容就到这里。总结一下:AAOS 的架构是分层的,核心服务通过 HAL 层和硬件打交道,应用框架则提供了方便的 API 和 UI 组件。理解了这个架构,你就能更好地设计你的车载应用了。