1. 课程导入
AOSP(Android Open Source Project)并不是一个“下载后 make 一下就能跑”的普通开源项目,而是一套由数百个 Git 仓库、多层构建系统、芯片平台适配层与硬件抽象层共同组成的超大型工程体系。学习本课程的目标,不是记住某一条命令,而是建立一张“从源码到可刷机镜像”的完整工程地图:知道每个阶段在做什么、依赖什么、出错时该往哪里查。
一、学习目标:从“会编译”到“能移植”
本课程围绕三个递进目标展开。第一层是构建能力:能独立完成环境搭建、源码同步、目标选择、编译与镜像产出。第二层是理解能力:能说清 Soong、Kati、Ninja、Make 之间的分工,理解 Android.bp 与 Android.mk 的关系,看懂构建日志中的模块依赖。第三层是移植能力:能为新硬件平台添加 BoardConfig、设备树配置、HAL 接口与内核适配,并完成 bring-up 验证。
二、核心概念:先建立术语坐标系
AOSP 工程中最容易混淆的是“层级”概念。源码层负责提供通用代码;设备层负责描述具体硬件;构建层负责把两者组合成产物;运行层负责在真实设备上验证。下表列出必须掌握的核心术语。
| 概念 | 所属层级 | 作用 |
|---|---|---|
| repo / manifest | 源码层 | 管理数百个 Git 仓库的同步与版本锁定 |
| lunch 目标 | 配置层 | 选择 product、build variant 与设备组合 |
| Android.bp | 构建层 | Soong 的模块描述文件,声明模块与依赖 |
| BoardConfig.mk | 设备层 | 定义芯片、分区、内核、编译器等板级参数 |
| HAL / HIDL / AIDL | 适配层 | 连接 Framework 与硬件驱动 |
| system.img / vendor.img | 产物层 | 可刷入设备的分区镜像 |
三、整体知识框架:一张图看清工程全貌
下图把 AOSP 构建与移植工程拆成五个相互衔接的层次:源码与工具链、构建系统、设备配置、镜像产物、设备验证。箭头表示数据与依赖的流动方向,也是排障时的追溯方向。
四、方法流程:一次完整构建的典型路径
无论目标平台是什么,构建流程都遵循相似顺序。下面是一段典型命令序列,可作为后续章节的操作基线。
# 1. 初始化仓库清单
repo init -u https://android.googlesource.com/platform/manifest -b android-14.0.0_r1
# 2. 同步源码(首次耗时较长)
repo sync -c -j8
# 3. 加载构建环境
source build/envsetup.sh
# 4. 选择目标
lunch aosp_arm64-userdebug
# 5. 全量编译
m -j$(nproc)
# 6. 产出镜像位于 out/target/product/<device>/
ls out/target/product/generic_arm64/*.img
这段流程背后隐藏着关键依赖:lunch 决定了加载哪个 BoardConfig 与 product 配置;Soong 解析 Android.bp 生成 Ninja 文件;Ninja 并行调度编译任务;最终由镜像打包工具生成分区镜像。理解这条链路,才能在编译失败时判断是配置问题、依赖问题还是工具链问题。
五、案例场景:新平台 bring-up 的典型顺序
假设拿到一块新的 ARM64 开发板,需要把 AOSP 移植上去。合理的顺序是:先确认内核与设备树能启动到串口输出;再配置 BoardConfig 中的分区表、内核路径与编译器;然后添加 device 目录下的 product 配置;接着适配显示、存储、网络等基础 HAL;最后跑通 adb 与 logcat,再逐步验证音频、摄像头等外设。顺序颠倒会导致“系统起不来却不知道是哪一层的问题”。
六、常见误区与复盘
- 误区一:把 AOSP 当成单一仓库。实际上它由 repo 管理的数百个仓库组成,版本必须通过 manifest 锁定,随意切换分支极易导致依赖错乱。
- 误区二:忽略 lunch 目标与设备配置的对应关系。选错目标会直接导致镜像无法启动,且报错往往出现在很晚的阶段。
- 误区三:只改 Android.mk 而忽略 Android.bp。新版本 AOSP 以 Soong 为主,模块声明位置错误会导致模块根本不被编译。
- 误区四:移植时先改 Framework。正确做法是先保证内核、HAL 与基础外设可用,再向上层适配。