2. 车载系统架构概览:Android Automotive OS架构、车载服务层、HAL层、应用层的关系
好,咱们进入第二章。说实话,很多刚接触车载Android的朋友,一上来就被各种分层概念搞懵了。什么AAOS、HAL、CarService……听着就头大。别急,今天我就带你把这些东西捋清楚。
我个人习惯,看一个系统先看它的骨架。Android Automotive OS(简称AAOS)的骨架,就是这四层:应用层、车载服务层、HAL层、Linux内核层。它们之间的关系,说白了就是「上层调下层,下层给上层干活」。
2.1 整体架构长什么样?
先给你一张图(脑补一下):
┌─────────────────────────────────────┐
│ 应用层 (Apps) │
│ (地图、音乐、设置、第三方App) │
├─────────────────────────────────────┤
│ 车载服务层 (Car Services) │
│ (CarService、CarPropertyManager) │
├─────────────────────────────────────┤
│ HAL 层 (Hardware Abstraction)│
│ (Vehicle HAL、Audio HAL、Camera) │
├─────────────────────────────────────┤
│ Linux 内核 + 驱动 │
│ (CAN总线、GPIO、I2C、SPI) │
└─────────────────────────────────────┘
嗯,就是这么个结构。每一层各司其职,又互相依赖。
2.2 应用层:用户看到的那一面
应用层就是用户直接操作的界面。比如中控屏上的导航、音乐播放器、车辆设置。这一层跟普通Android App开发很像,但有个关键区别——它必须通过车载服务层才能跟车辆硬件打交道。
举个例子,你想在App里获取当前车速。你不能直接去读CAN总线,那太底层了。你得调用CarService提供的API。我在项目中遇到过,有新手直接去读/sys/class/...下的节点,结果权限不够,App直接崩溃。嗯,这个坑我踩过。
核心要点:应用层只负责UI和业务逻辑,不直接操作硬件。所有车辆数据都通过CarService获取。
2.3 车载服务层:系统的「大脑」
这一层是AAOS最核心的部分。它叫CarService,运行在系统进程中。你想想看,它要干的事可多了:
- 管理车辆属性(车速、里程、车门状态)
- 处理车辆事件(转向灯、刹车、空调)
- 提供API给上层App调用
- 跟HAL层通信,下发指令
CarService内部又分了好几个模块:
| 模块 | 作用 |
|---|---|
| CarPropertyManager | 管理车辆属性,比如车速、油量 |
| CarSensorManager | 管理传感器数据,比如加速度、陀螺仪 |
| CarAudioManager | 管理车载音频,比如导航音、电话音 |
| CarHvacManager | 管理空调系统 |
我记得第一次看CarService源码时,发现它竟然有200多个API。当时我就想,这玩意儿真不是一个人能搞定的。
小技巧:调试车载服务层时,可以用dumpsys car_service命令查看当前车辆状态。这个命令能帮你快速定位问题。
2.4 HAL层:硬件和系统的「翻译官」
HAL层,全称Hardware Abstraction Layer。说白了,它就是一层「适配器」。为什么需要它?因为不同车厂的硬件千差万别。有的用CAN总线,有的用LIN总线,还有的用以太网。如果没有HAL层,CarService就得为每种硬件写一套代码,那不得累死?
HAL层的核心是Vehicle HAL。它定义了一套标准接口,CarService只管调用这些接口,至于底层是CAN还是LIN,HAL帮你搞定。
// Vehicle HAL 的核心接口示例
public class VehicleHalClient {
// 获取车辆属性
public VehiclePropValue getProperty(int propId, int areaId) {
// 这里会调用底层驱动
// 可能是CAN总线,也可能是其他协议
}
// 设置车辆属性
public void setProperty(VehiclePropValue propValue) {
// 下发指令到硬件
}
}
我曾经在一个项目里,HAL层死活读不到车速数据。查了两天,最后发现是CAN总线上的ID映射错了。你想想看,一个ID不对,整个系统都跑不起来。所以做HAL开发,一定要跟硬件工程师对好协议。
注意:HAL层是C++实现的,运行在独立的进程中。如果HAL崩溃,CarService会收到死亡通知,然后尝试重启。但重启期间,所有车辆功能都会失效。所以HAL的稳定性至关重要。
2.4 各层之间怎么通信?
这个问题很关键。各层之间不是直接调用的,而是通过Binder和HIDL来通信。
- 应用层 ↔ 车载服务层:通过Android标准的Binder机制。App绑定CarService,然后调用API。
- 车载服务层 ↔ HAL层:通过HIDL(HAL Interface Definition Language)。这是Android专门为HAL设计的IPC机制。
- HAL层 ↔ 内核驱动:通过ioctl、read/write等系统调用。
嗯,这里要注意。HIDL是Android 8.0引入的,它让HAL层可以独立更新,不用跟着系统一起编译。这个设计很巧妙,车厂可以单独升级HAL,而不影响上层。
2.5 实际项目中的分层经验
说了这么多理论,来点实际的。我在做车载项目时,遇到过这么几个典型问题:
- 应用层直接读硬件:有同事图省事,在App里直接读/sys/class/gpio。结果Android 10以后权限收紧,直接报错。正确做法是通过CarService获取。
- HAL层死锁:有一次HAL层在获取属性时加了锁,CarService也在等这个锁,结果两边互相等,系统卡死。后来我们规定,HAL层不能长时间持有锁。
- 属性ID冲突:不同车厂自定义的属性ID可能冲突。Google建议用0x1000-0x1FFF作为厂商自定义范围,但很多人不知道,直接用了0x0001,结果跟系统属性冲突。
避坑指南:我曾经因为HAL层返回的数据格式不对,导致CarService解析错误,整个空调控制面板失灵。后来我养成了一个习惯——在HAL层加日志,每次返回数据都打印出来。这样调试起来快多了。
2.6 小结
好了,这一章的内容就这些。总结一下:
- AAOS分四层:应用层、车载服务层、HAL层、内核层
- 应用层只管UI,不碰硬件
- CarService是核心,管理所有车辆功能
- HAL层是适配器,屏蔽硬件差异
- 各层通过Binder和HIDL通信
下一章,我们会深入CarService的内部,看看它到底是怎么工作的。到时候我会带你手撕源码,保证让你看明白。
公众号:蓝海资料掘金营,微信deep3321