3、源码结构解析:AOSP 顶层目录详解

拿到 AOSP 源码之后,第一件事是什么?

我个人习惯,不是急着编译,而是先逛一圈顶层目录。就像搬进新房子,总得先看看客厅、厨房、卧室都在哪。AOSP 的顶层目录,就是整栋房子的户型图。搞懂了它,后面编译、调试、定制 ROM 的时候,你才知道该去哪找东西。

3.1 整体俯瞰:AOSP 顶层目录长什么样?

你同步完源码,在根目录下执行 ls,会看到几十个文件夹。别慌,核心的就那么几个。我画了一张图,帮你快速建立全局认知:

AOSP 顶层核心目录结构 AOSP 根目录 build device hardware system vendor soong / make / blueprint 厂商 / 产品 / BoardConfig libhardware / interfaces core / bt / net / vold 二进制驱动 / 闭源库 每个目录都有明确分工,定制 ROM 主要改 device、vendor、system build 系统决定了你用什么方式编译整个项目 从根目录出发,逐层深入

3.2 build —— 编译系统的总指挥部

build/ 目录,说白了就是整个 AOSP 的编译引擎。你执行 source build/envsetup.shlunch 的时候,调用的就是这里的东西。

里面主要有三块:

  • soong/:Android 新的构建系统,基于 Go 语言。现在新项目都用它。
  • make/:传统的 Makefile 构建。老项目还在用,但 Google 在逐步迁移。
  • blueprint/:soong 的底层构建描述语言。你写的 Android.bp 文件,就是 blueprint 格式。
💡 我的经验: 如果你要新增一个模块,建议直接写 Android.bp,别再用 Android.mk 了。我在 2022 年接手一个项目时,发现还有人在用 Makefile 写新模块,结果编译报错查了半天,最后发现是 soong 和 make 的混合模式出了问题。

3.3 device —— 你的硬件平台在这里安家

device/ 目录,是每个硬件平台的「身份证」。你想想看,不同的手机厂商、不同的芯片方案,它们的硬件配置、内核参数、分区大小都不一样。这些差异,全写在这里。

目录结构一般是:device/<厂商名>/<产品名>/

举个例子:

device/google/pixel/
├── BoardConfig.mk        # 主板配置:芯片、内存、分区大小
├── device.mk             # 产品定义:包含哪些模块
├── system.prop           # 系统属性默认值
├── overlay/              # 资源覆盖层
└── sepolicy/             # SELinux 策略

这里有个坑,我踩过好几次:BoardConfig.mk 里的 TARGET_BOARD_PLATFORM 一定要写对。有一次我帮同事排查编译错误,发现他写了个不存在的平台名,结果编译链直接报找不到 HAL 实现。嗯,这种低级错误,查起来最费时间。

3.4 hardware —— 硬件抽象层的大本营

hardware/ 目录,存放的是 Android 硬件抽象层(HAL)的接口定义和参考实现。说白了,就是告诉上层「硬件长什么样,该怎么操作」。

重点看这几个:

  • libhardware/:HAL 的核心框架。里面定义了 hw_module_thw_device_t 这些基础结构体。
  • interfaces/:HIDL 接口定义。Android 8.0 之后,HAL 都用 HIDL 来描述了。
  • broadcom/、ti/、qcom/:芯片厂商的参考实现。不过现在很多厂商都把这些移到 vendor/ 里了。
⚠️ 注意: 不要直接修改 hardware/interfaces/ 里的 HIDL 文件。这些是 Google 定义的稳定接口。我曾经见过有人为了加一个私有接口,直接改了官方的 types.hal,结果升级 Android 版本时,所有依赖这个接口的模块全崩了。

3.5 system —— Android 系统的核心守护者

system/ 目录,是 Android 系统服务的「心脏」。里面跑着各种核心守护进程和库。

子目录 作用 我常改的地方
core/ init、logd、adbd 等核心守护进程 init.rc 启动脚本,定制开机流程时必改
bt/ 蓝牙协议栈(Fluoride) 很少动,除非要修蓝牙兼容性问题
net/ 网络相关服务(netd、dns) 改过 DNS 缓存策略,解决过网页加载慢的问题
vold/ 存储管理(挂载、加密) 定制分区加密方案时必看
sepolicy/ SELinux 安全策略 加新设备节点时,这里不配好,服务直接起不来

我个人觉得,system/core/init/ 是定制 ROM 时最常打交道的地方。你想想看,开机动画怎么改?开机自启服务怎么加?selinux 权限怎么放?全在这。

3.6 vendor —— 厂商私货的藏身之处

vendor/ 目录,是芯片厂商和 OEM 放「私货」的地方。比如高通的 GPU 驱动、博通的 WiFi 固件、还有各种闭源的 HAL 实现。

为什么要有这个目录?

  • 闭源二进制:很多硬件驱动不开源,只能以 .so 或 .img 形式提供。
  • 厂商定制:比如小米的快充方案、华为的相机算法,都放在这里。
  • 分区独立:编译时 vendor/ 会单独打包成 vendor.img,方便 OTA 升级时只更新 vendor 分区。
🔑 关键点: 如果你在做定制 ROM,vendor/ 里的东西尽量不要动。动了之后,厂商的 OTA 包可能就刷不进去了。我见过有人为了精简系统,把 vendor 里的某个 .so 删了,结果相机直接打不开——因为那个 .so 是相机 HAL 的依赖。

3.7 其他值得关注的目录

除了上面五个核心目录,还有几个也值得了解:

  • frameworks/:Android 框架层,Java 代码为主。改 UI、加系统服务都在这里。
  • packages/:系统应用,比如 Settings、Launcher、Phone。
  • external/:第三方开源库,比如 SQLite、libpng、curl。
  • kernel/:有些 AOSP 版本会包含内核源码,但大部分厂商会单独维护。

嗯,这里要注意:external/ 里的库,尽量不要自己改版本。有一次我想把 libcurl 升级到最新版,结果发现 AOSP 里好几个模块都依赖特定版本的 API,一升级编译直接报几百个错误。后来我学乖了,除非有安全漏洞,否则不动它。

3.8 实战建议:如何快速定位你要改的目录?

刚开始接触 AOSP 时,最头疼的就是「我要改某个功能,该去哪个目录找?」

我总结了一个简单的方法:

  1. 改开机流程system/core/init/ + device/<厂商>/<产品>/init.rc
  2. 改系统属性device/<厂商>/<产品>/system.prop
  3. 加硬件支持hardware/interfaces/ + vendor/<厂商>/
  4. 改系统 UIframeworks/base/ + packages/apps/
  5. 改编译配置build/soong/ + device/<厂商>/<产品>/BoardConfig.mk

这个方法,我在带新人时一直在用。你想想看,只要记住「功能对应目录」这个映射关系,AOSP 源码就不再是一团乱麻了。


公众号:蓝海资料掘金营,微信deep3321