2. AOSP 源码结构:源码根目录结构、关键目录的作用
好,咱们正式开始看代码了。不过别急,先别一头扎进某个文件里。我刚开始接触AOSP时,第一反应就是直接翻 frameworks/base 的代码,结果被目录结构绕晕了。后来我才明白——先看懂根目录下每个文件夹是干嘛的,比什么都重要。
说白了,AOSP 源码根目录就像一个大仓库。每个文件夹负责一类活。你只要知道哪个目录管什么,遇到问题就知道去哪找答案。
2.1 根目录下都有什么?
你下载完 AOSP 源码后,在根目录执行 ls,会看到一堆文件夹。我挑几个最核心的说说:
- build/ —— 构建系统的核心,所有编译逻辑都在这里
- device/ —— 具体设备的配置和适配代码
- vendor/ —— 厂商私有的二进制、驱动、库
- hardware/ —— 硬件抽象层(HAL)和硬件相关的代码
- frameworks/ —— Android 框架层,应用开发者最常接触的部分
- packages/ —— 系统应用,比如设置、电话、短信
- kernel/ —— Linux 内核(有些版本不直接包含)
- external/ —— 第三方开源库,比如 SQLite、libpng
- system/ —— 底层系统服务,比如 init、adb、logd
- art/ —— Android Runtime,负责应用运行
嗯,这里要注意:不是所有目录你都会用到。比如你只做系统应用开发,那 frameworks 和 packages 才是你的主战场。但如果你是做系统移植或 BSP 开发,那 device、vendor、hardware 就是你的命根子。
2.2 build/ 目录:构建系统的发动机
这个目录,说白了就是整个 Android 编译的指挥中心。你执行 make 或 m 命令时,背后就是 build/ 在调度一切。
我个人习惯,遇到编译问题先看 build/ 下的几个关键文件:
- build/envsetup.sh —— 初始化环境,设置
lunch、m、mm等命令 - build/core/main.mk —— 构建入口,定义了整个编译流程
- build/soong/ —— 新一代构建系统(替代了老旧的 Make),用 Blueprint 文件
- build/make/ —— 传统的 Make 构建系统,现在逐渐被 Soong 取代
核心概念:AOSP 构建系统正在从 Make 迁移到 Soong。Soong 使用 .bp(Blueprint)文件,比 Make 更简洁、更易读。如果你看到 Android.mk 和 Android.bp 同时存在,优先看 .bp 文件。
我记得有一次,同事编译某个模块一直报错,折腾了半天。最后发现是 Android.bp 里少写了一个依赖。嗯,这种坑我踩过不止一次。
2.3 device/ 目录:你的设备在这里安家
device/ 目录存放的是具体设备的配置和适配代码。每个设备厂商、每个产品线,都会在这里有一个子目录。
举个例子,Google 的 Pixel 设备:
device/google/
├── pixel/ # Pixel 系列通用配置
├── pixel6/ # Pixel 6 专属配置
├── pixel7/ # Pixel 7 专属配置
└── common/ # 公共配置
每个设备目录下通常包含:
- BoardConfig.mk —— 板级配置,比如芯片型号、内存大小、分区布局
- device.mk —— 设备相关的 Makefile,指定要编译哪些模块
- AndroidProducts.mk —— 定义产品名称和编译目标
- overlay/ —— 资源覆盖,可以修改系统默认的 UI 和配置
- init.*.rc —— 设备启动时的初始化脚本
小技巧:如果你想快速了解一个设备支持什么硬件,直接看它的 BoardConfig.mk。里面会定义屏幕分辨率、摄像头数量、传感器类型等关键信息。
2.4 vendor/ 目录:厂商的“黑盒子”
vendor/ 目录,说白了就是厂商不想开源的那部分代码。比如硬件驱动、闭源库、预编译的二进制文件。
为什么要有这个目录?因为 AOSP 是开源的,但很多硬件厂商(比如高通、联发科)的驱动和库是闭源的。它们不能放在 device/ 或 hardware/ 里,所以单独放在 vendor/ 下。
vendor/ 的典型结构:
vendor/
├── google/ # Google 的闭源组件(比如 GMS)
├── qcom/ # 高通的闭源驱动和库
├── mediatek/ # 联发科的闭源组件
└── your_company/ # 你自己的厂商目录
我曾经在一个项目里,遇到系统启动时摄像头打不开。查了半天,最后发现是 vendor/ 下的摄像头 HAL 库版本不对。嗯,这种问题在 vendor/ 里很常见——因为你看不到源码,只能靠日志和二进制替换来排查。
避坑指南:vendor/ 下的文件通常是预编译的 .so 或 .img,不要随意修改。如果你需要调试,先确认 vendor 分区是否挂载正确,以及 SELinux 策略是否允许访问。
2.5 hardware/ 目录:硬件抽象层(HAL)的根据地
hardware/ 目录存放的是硬件抽象层(HAL)的接口定义和参考实现。HAL 的作用,说白了就是给上层框架提供一个统一的硬件操作接口,不管底层是什么芯片,上层代码都不用改。
常见的子目录:
- hardware/libhardware/ —— HAL 的核心框架和接口定义
- hardware/libhardware_legacy/ —— 旧的 HAL 实现(逐渐被淘汰)
- hardware/ril/ —— 无线接口层,负责手机通信
- hardware/interfaces/ —— HIDL 接口定义(Android 8.0 之后的新方式)
举个例子,摄像头 HAL 的接口定义就在 hardware/libhardware/include/hardware/camera.h 里。你打开看看,会发现它定义了一组函数指针:
typedef struct camera_device {
// 打开摄像头
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
// 关闭摄像头
int (*close)(struct hw_device_t* device);
// ... 其他操作
} camera_device_t;
你看,上层框架只需要调用这些函数,不用关心底层是高通还是联发科的摄像头。这就是 HAL 的魅力。
2.6 一张图看懂核心目录的关系
下面这张图,我画了 AOSP 中几个关键目录之间的协作关系。你一看就明白:
从这张图你能看到:
- packages/ 和 frameworks/ 是上层,负责应用和框架逻辑
- hardware/ 是中间层,隔离了硬件差异
- device/ 和 vendor/ 是底层,负责具体硬件适配和闭源组件
- build/ 贯穿所有层,负责把代码编译成可运行的镜像
- kernel/ 是最底层,直接和硬件打交道
2.7 小结
好了,这一章的内容就这些。你记住一句话就行:build/ 管编译,device/ 管设备,vendor/ 管闭源,hardware/ 管抽象。这四个目录,是 AOSP 源码结构的四根柱子。
下一章,我们会深入 build/ 目录,看看 lunch、m、mm 这些命令到底是怎么工作的。到时候你会明白,为什么我总说“理解了构建系统,就理解了 Android 的一半”。