第三章:源码结构解析 — AOSP顶层目录与车机相关目录
好,咱们现在正式开始接触AOSP源码。说实话,我第一次下载完AOSP的时候,看着那一堆文件夹,心里是有点懵的。一百多个G的代码,从哪看起?
别急,我帮你理一理。这一章,咱们只挑最核心的目录讲。你记住一句话:搞懂顶层目录,你就拿到了Android移植的钥匙。
3.1 AOSP顶层核心目录
先看几个你一定会打交道的目录。我按重要程度排了个序,你心里有个数。
3.1.1 art — Android Runtime
这是Android的运行时环境。说白了,就是App怎么跑起来的。ART负责把dex字节码编译成本地机器码。我当年在移植一个低配车机时,发现ART的GC(垃圾回收)策略导致界面卡顿,后来调了编译模式才解决。嗯,这个坑后面细讲。
3.1.2 bionic — 标准C库
这是Android自己的C库实现,替代了glibc。为什么不用glibc?因为glibc太臃肿了,不适合嵌入式设备。bionic更轻量,而且对多线程支持更好。你在移植过程中,如果遇到某些第三方库链接报错,十有八九是bionic和glibc的差异导致的。
3.1.3 build — 编译系统
这个目录你得重点看。它包含了所有编译相关的脚本、Makefile、配置模板。Android的编译系统经历过从Android.mk到Soong(Blueprint)的演变。我个人习惯直接看build/soong/下面的代码,因为新项目基本都用Soong了。
核心文件:
build/make/core/— 旧的Makefile核心逻辑build/soong/— 新的编译系统,用Go语言写的build/envsetup.sh— 你每次编译前都要source这个文件
3.1.4 device — 设备配置
这个目录存放各个厂商的设备配置。比如你的车机用的是高通平台,那就在device/qcom/下面。每个设备目录里都有BoardConfig.mk、device.mk、vendorsetup.sh等文件。我建议你从device/generic/开始看,那是Google提供的参考实现。
3.1.5 hardware — 硬件抽象层
HAL层就在这里。它定义了硬件厂商如何实现Android的硬件接口。比如摄像头、音频、传感器等。车机移植中,你主要关注hardware/libhardware/和hardware/interfaces/。前者是老式的HAL,后者是Treble架构下的HIDL接口。
3.1.6 kernel — 内核
注意,这个目录在AOSP里是空的!它只是一个占位符。真正的内核代码你得从kernel.org或者芯片厂商那里获取。我记得第一次移植时,傻乎乎地在AOSP里找内核代码找了半天……后来才明白,内核是独立维护的。
3.1.7 packages — 应用包
系统自带的App都在这里。比如设置、电话、联系人、Launcher等。车机移植中,你可能会修改packages/apps/Settings/来添加车机专属设置项,或者替换packages/apps/Launcher3/为车机桌面。
3.1.8 system — 系统核心
这个目录包含了核心系统服务、守护进程、库文件等。比如system/core/里有init进程、logd、adbd等。你想想看,init进程是Android启动的第一个用户空间进程,它解析init.rc脚本,启动各种服务。如果车机启动卡在某个阶段,十有八九要来这里查。
3.2 车机相关目录
好,上面是通用目录。下面这两个目录,是专门为车机准备的。Google从Android 8.0开始,正式把车机支持放进了AOSP主线。
3.2.1 device/generic/car — 车机参考设备
这个目录是Google提供的车机参考实现。它包含了车机专属的配置、权限、预装应用等。我带你看看里面有什么:
device/generic/car/
├── emulator/ # 模拟器配置
├── car_common/ # 车机通用配置
│ ├── car_product.mk # 产品定义文件
│ ├── packages/ # 预装应用列表
│ └── overlay/ # 资源覆盖层
└── car_ui_portrait/ # 竖屏UI配置
你移植车机时,第一步就是参考这个目录的结构,创建你自己的产品目录。比如:device/yourcompany/car_product/。
我的经验: 别直接修改device/generic/car,而是复制一份出来改。这样方便以后对比Google的更新。
3.2.2 hardware/interfaces/automotive — 车机HAL接口
这个目录定义了车机专属的硬件抽象接口。比如车辆网络(CAN总线)、座舱传感器、车载诊断等。Google用HIDL语言定义了这些接口,硬件厂商需要实现它们。
常见的接口有:
| 接口名称 | 功能描述 | 我遇到的坑 |
|---|---|---|
| IVehicle | 车辆属性访问(车速、车门状态等) | 曾经因为属性ID定义不一致,导致App读不到车速 |
| ICarAudio | 车载音频路由(导航、电话、媒体独立声道) | 音频焦点管理没处理好,导航和音乐同时出声 |
| ICarCluster | 仪表盘显示控制 | 仪表盘刷新率不够,导致指针动画卡顿 |
| ICarPower | 车辆电源管理(ACC、休眠、唤醒) | ACC断电后系统没及时休眠,电瓶亏电了 |
警告: 车机HAL接口的版本号很重要。比如android.hardware.automotive.vehicle@2.0和@2.1,接口有变化。我曾经因为用了旧版本的接口,导致新功能无法启用。记得检查hardware/interfaces/automotive/下的current.txt文件,看当前支持的版本。
3.3 目录之间的依赖关系
你可能会问:这些目录之间怎么配合的?我画个简单的流程:
- 编译入口:build/ 目录下的编译系统读取 device/ 目录下的产品配置
- 选择组件:根据配置,决定编译哪些 packages/ 里的应用和 system/ 里的服务
- 链接库:应用和服务依赖 bionic/ 提供的C库,以及 art/ 提供的运行时
- 硬件交互:通过 hardware/ 里的HAL接口,调用 kernel/ 里的驱动
- 车机专属:device/generic/car 提供车机配置,hardware/interfaces/automotive 提供车机HAL
嗯,这个流程你记在心里。以后遇到问题,就按这个链条去排查。
3.4 本章小结
这一章我们看了AOSP的顶层目录。你不需要记住每个目录的细节,但要知道:
- art、bionic、build 是基础,几乎不会动
- device、hardware、kernel 是移植重点,你要花大量时间在这里
- packages、system 是功能定制,根据需求修改
- device/generic/car 和 hardware/interfaces/automotive 是车机专属,必须吃透
下一章,我们开始动手搭建编译环境。到时候你会真正体会到,这些目录是怎么串起来的。
课后作业: 下载AOSP源码后,进入device/generic/car目录,看看car_product.mk里引用了哪些模块。然后对比一下你手上的车机方案,看看哪些模块是通用的。