第2章 开发环境准备:AOSP源码下载、编译环境搭建、模拟器与真机调试配置

2.1 环境准备概述

Framework 层自定义 Service 的开发无法脱离完整的 AOSP 编译环境。本章从零搭建一套可反复使用的构建与调试基础设施。整个流程分为三条主线:源码下载(获得原始代码树)、编译环境构建(安装工具链、配置构建参数)、目标运行环境(模拟器与真机)。下图展示总体工作流。

AOSP 开发环境搭建流程 源码下载 依赖安装 初始化构建 选择目标(lunch) 编译(m / make) 模拟器 / 刷机 日志与断点调试 🔁 增量编译 / ccache 📌 真机需解锁 bootloader

2.2 硬件与软件前提

编译 AOSP 对机器资源要求较高。下表列出推荐的最低与建议配置。

项目最低要求建议配置
CPU4 核 x86_648 核或更多
内存8 GB16 GB 或更大
磁盘剩余空间100 GB(源码 + 编译)300 GB 以上(SSD)
操作系统Ubuntu 18.04+ / macOS 12+Ubuntu 22.04 LTS
文件系统大小写敏感(Linux 默认满足,macOS 需创建大小写敏感卷)大小写敏感 + 开启 casefold
Python3.8+3.11
Git2.25+2.40+
JDK11(aliyun 镜像或 OpenJDK)17(Unbundled 模块需要)
大小写敏感文件系统:AOSP 构建系统依赖文件名大小写差异(例如 Readme.txt 与 readme.txt)。macOS 默认是大小写不敏感,必须新建一个大小写敏感的磁盘映像(Disk Utility → APFS Case-sensitive)并在其内操作。

2.3 AOSP 源码下载

2.3.1 安装 Repo 工具

Google 使用 repo 管理 AOSP 的数百个 Git 仓库。安装方法如下:

mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=$PATH:~/bin

2.3.2 同步源码

创建专用目录并初始化 manifest。以 android-14.0.0_r15 标签为例:

mkdir ~/aosp && cd ~/aosp
repo init -u https://android.googlesource.com/platform/manifest \
          -b android-14.0.0_r15
repo sync -c -j8
  • -c 只下载当前分支(节省带宽)。
  • -j8 并行拉取任务数,可依据 CPU 核心数调整。
  • 国内用户可替换仓库地址为清华源或中科大源:将 https://android.googlesource.com 换为 https://mirrors.tuna.tsinghua.edu.cn/git/AOSP。

2.3.3 常见问题

网络中断:若同步中途断连,重新执行 repo sync 会断点续传,但可能因 GIT 对象损坏报错。此时先执行 repo sync --no-repo-verify -l 锁定当前已下载的仓库,再逐仓库修复。
# 查看 manifest 分支
repo info -o | grep -E "Manifest branch"
# 切换分支(谨慎操作,会丢弃未提交修改)
repo init -b android-13.0.0_r30
repo sync -c -j8

2.4 编译环境搭建

2.4.1 安装系统依赖(Ubuntu 22.04)

sudo apt update
sudo apt install git-core gnupg flex bison build-essential zip curl zlib1g-dev \
  libc6-dev-i386 libncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev \
  libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig python3 python3-pip \
  openjdk-11-jdk

不同 Android 版本依赖略有差异,具体查阅 source.android.com/setup/build/initializing。

2.4.2 初始化构建环境

每次打开新终端都要执行以下命令设置环境变量与函数。

cd ~/aosp
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-userdebug
  • lunch 会加载对应产品的 BoardConfig.mk、product.mk 等。
  • userdebug 版本保留 Root 与调试权限,适合 Framework 开发。

常用 target 速查:

lunch 名称说明
aosp_cf_x86_64_phone-userdebugCuttlefish 模拟器(x86_64)
aosp_pixel6-userdebugPixel 6 真机
aosp_oriole-userdebugPixel 6(代号 oriole)
sdk_phone_x86_64-userdebug低配 emulator(不支持一些硬件加速)

2.4.3 执行编译

m -j$(nproc) 2>&1 | tee build.log
  • m 是 AOSP 封装的 make 命令,自动定位 build/make。
  • $(nproc) 获取 CPU 核心数。
  • 使用 ccache 加速重复编译:export USE_CCACHE=1 && ccache -M 50G。
增量编译:首次全编译需要 2–3 小时。后续修改 Framework 代码后,只需运行 m 或 mm(在模块目录下),会触发依赖重建,通常 1–3 分钟完成。

2.5 模拟器调试配置

2.5.1 编译模拟器系统镜像

确保已经 lunch aosp_cf_x86_64_phone-userdebug 并执行 m 成功。模拟器镜像在 out/target/product/vsoc_x86_64/ 目录下。

2.5.2 启动 Cuttlefish 模拟器

source build/envsetup.sh
lunch aosp_cf_x86_64_phone-userdebug
cvd start --daemon

如果使用传统 emulator(非 Cuttlefish),需先编译 sdk_phone_x86_64 target,然后运行:

emulator -writable-system -no-snapshot -show-kernel

2.5.3 连接 ADB 与查看日志

adb devices          # 确认设备在线
adb root             # 获得 root shell
adb logcat -v threadtime *:V         # 输出所有日志
adb logcat -s "MyService"            # 过滤指定 Tag

2.6 真机调试配置

2.6.1 解锁 Bootloader

各厂商解锁方式不同,Pixel 设备步骤:

# 开启开发者选项 → OEM 解锁 → 启用 USB 调试
adb reboot bootloader
fastboot flashing unlock
# 按音量键选择 Unlock the bootloader,按电源键确认
fastboot reboot

2.6.2 刷入自定义镜像

编译产出在 out/target/product/<device>/ 下,常用命令:

fastboot flash boot out/target/product/oriole/boot.img
fastboot flash system out/target/product/oriole/system.img
fastboot flash vendor out/target/product/oriole/vendor.img
fastboot reboot
刷机风险:确保当前系统与编译目标完全匹配(同一 Android 版本和 kernel 分支)。刷错镜像可能导致变砖,需提前备份 /data 分区。

2.6.3 启用 Root 调试

adb root          # 若失败,尝试 adb shell 后执行 su
adb remount       # 将 system 分区重新挂载为可写(仅 userdebug 或 eng 版本)

2.7 调试要点与日志

  • 日志级别:Framework Service 常使用 Log.d/Log.i/Log.e。过滤 Tag 为服务类名。
  • 断点调试:修改代码后执行 m services(只编译 Services 模块),然后 adb sync 或重新刷入 system.img。
  • 堆栈抓取:adb shell dumpsys activity services 查看所有运行中的 Service。
  • GDB/LLDB:需要编译带有 debug 符号的版本(eng 版本默认包含)。在模拟器中可通过 gdbclient 脚本附加到进程。

2.8 常见错误与解决方案

错误现象原因解决
fatal: unable to access '...'网络不通或 DNS 异常换国内镜像源;配置 git config --global http.proxy
Out of memory: Killed process物理内存不足,内核 OOM Killer减少 -j 并发数,增大 Swap,或使用 m -j4
Jack server not running(老版本)Jack 编译服务未启动升级 Android 版本至 9.0+(改用 Jack 后的 Soong)
Cannot find module with tag 'something'lunch target 不对应或 product 配置缺失检查 device/ 和 product/ 目录;重新 lunch 正确 target
emulator: ERROR: x86 emulation currently requires hardware acceleration!未安装 KVM(Linux)或 HAXM(macOS/Windows)sudo apt install qemu-kvm;macOS 安装 Intel HAXM
fastboot: error: cannot load 'boot.img'镜像路径错误确认 lunch target 后进入 out/target/product/<device>/ 检查文件

2.9 性能与稳定性优化

  • ccache:设置缓存上限,推荐 50 GB:ccache -M 50G。第二次全编译可减少 40% 以上时间。
  • ninja 并行度:通过 m -jN 避免系统过载。若使用 ninja 直接调用,可设置 SNIPPET_NINJA_JOBS=8。
  • 使用 RAM 盘:将编译中间产物放到 tmpfs(内存盘),大幅降低 I/O 延迟。示例:
sudo mkdir /mnt/rambuild
sudo mount -t tmpfs -o size=64G,mode=0755 tmpfs /mnt/rambuild
mkdir -p /mnt/rambuild/out
ln -sf /mnt/rambuild/out ~/aosp/out   # 符号链接替换 out 目录
  • 增量编译习惯:只修改 Framework 层代码时使用 m services 或 m frameworks/base,避免全量 make。
  • 清理 stale 产物:若出现诡异编译错误,执行 make clean 或 rm -rf out 后再全量编译。

2.10 本章小结