不管是 Android App 开发工程师还是 Android 系统开发工程师,对 Android 系统有一定的了解是很有必要的,正好我这几天在家里搭建了个开发环境,把过程分享出来,有需要的人可以看一下。
大概的步骤包含下面几个:
- 安装 Ubuntu 系统
- 配置 Ubuntu 系统
- 安装必备的软件
- 配置网络访问环境 (可选)
- 下载 AOSP 代码
- 配置编译环境并编译 Pixel 的代码
- 刷机
- 修改和编译 Framework 、Service、Res
版本说明(2026-10-13 核查):原文是 2018 年的环境记录。截图可见 Ubuntu 18.04.1、
PLATFORM_VERSION_CODENAME=Q、aosp_sailfish-userdebug,但未保存完整 manifest,不能重建当时的 master 提交。旧 Pixel/刷机部分作为历史流程保留;新增示例固定 Android 16 的android-16.0.0_r1、Ubuntu 22.04 x86_64、Cuttlefish x86_64,不代表最新发布,也不是给初代 Pixel 刷 Android 16 的教程。
原来建议的“512 GB SSD + 一台 Pixel”要分情况看。新建现代 AOSP 工作站时,可以参考当前官方环境要求:64 位 x86 Linux、至少 400 GB 可用空间和 64 GB RAM。磁盘标称 512 GB 不等于还有 400 GB 可用,多源码树和输出会继续占空间;这些是工作站规划基线,不是所有旧版本的硬性门槛。仅阅读源码可以少配一些;运行本文的 Cuttlefish 示例还需要可用的 KVM,真机不是必需品。
安装 Ubuntu 系统
原文使用 Ubuntu 18.04,它的常规安全维护已于 2023 年 5 月结束,扩展维护另有条件,见 Ubuntu 生命周期。新示例选用 Ubuntu 22.04 LTS,而不是继续使用那条旧 18.04.1 ISO 镜像链接。
- 从 Ubuntu 22.04 官方发行目录获取 amd64 安装镜像,按目录中的校验信息检查下载。
- 制作启动 U 盘,并在分区前备份原系统数据。
- 安装到准备好的 Linux 主机;虚拟机也可以使用,但要分配足够磁盘和内存,运行 Cuttlefish 时还需向客体提供 KVM/嵌套虚拟化。虚拟机里能编译,不代表一定能运行虚拟设备。
下面是我当时的桌面。当前 AOSP 主机要求以 Linux 为准,不能把本文命令直接当成 macOS 或 Apple Silicon 的原生构建流程。

配置 Ubuntu 系统
输入法和编辑器按个人习惯选择。Vim 可用 sudo apt install vim 安装;adb、fastboot 可通过 Android Studio SDK Manager 或官方 SDK Platform-Tools获取。构建 AOSP 后也会得到主机工具,使用时先确认终端实际找到的是哪一份,避免混用旧工具:
1 | command -v adb |
Linux 真机连接还要完成 USB 调试授权和设备访问权限配置;能列出设备后,再进行后面的部署。
安装必备的软件
我当时列的 VS Code、Android Studio、Meld 是编辑/比较工具;Wine、WPS 和搜狗输入法是自己的桌面使用习惯,都不是 AOSP 编译依赖。按自己需要安装即可,系统构建依赖见后面的章节。
配置网络访问环境 (可选)
根据本地环境准备稳定的源码访问方式。Repo 自身的下载源与 AOSP manifest/项目镜像是不同入口,只替换 manifest 地址未必解决所有连接问题。
下载 AOSP 代码
官方下载说明支持用 -b 选择标签或分支。下面使用固定标签 android-16.0.0_r1;它对应 Android 16,见版本与构建号表。不要像旧文那样省略分支,再把后来下载的内容当成当年的环境。
repo 下载
Ubuntu 上可先安装发行版提供的 Repo launcher:
1 | sudo apt update |
官方目前要求 launcher 2.4 或更高。若发行版软件源没有合适的包,使用官方手动安装步骤,包括签名校验;旧文直接下载到 ~/bin/repo 的几行不再作为完整安装流程。
建立工作目录
选择空间足够的新目录;已有其他版本源码时,不要直接在原树里换标签:
1 | mkdir -p ~/aosp-16-r1 |
初始化仓库
1 | repo init -u https://android.googlesource.com/platform/manifest -b android-16.0.0_r1 |
如果需要清华镜像,按镜像站当前说明把上面命令的 -u 改为 https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest,保留同一个 -b。选择一个入口初始化即可,镜像同步时间也可能影响某个标签是否已可用。
下载代码(-c --no-tags 能下载更少的代码)
旧标题中的参数不是版本锁定手段。-c 缩小到 manifest 所需的分支/修订;--no-tags 只影响标签抓取,不能代替 -b。下面沿用官方的同步形式,-j8 是同步并发示例,可按网络和主机资源降低:
1 | repo sync -c -j8 |
同步成功后再导出 manifest,记录每个项目的实际提交。任何项目同步失败都应先处理,不要带着不完整源码进入编译。
配置编译环境并编译 Pixel 的代码
这一节区分两个目标:原图中的初代 Pixel sailfish 是历史案例;新增命令编译 Cuttlefish。产品名、源码、专有二进制和输出必须匹配,不能把两个目标的步骤拼起来执行。
配置编译环境
安装jdk
原文安装 openjdk-8-jdk 的做法不能通用于现代 AOSP。本文固定的 Android 16 源码由构建系统选择 Java 工具链;envsetup.sh 设置 ANDROID_JAVA_HOME/JAVA_HOME,不要强行覆盖成系统 JDK 8。旧版本需要什么 JDK,应按对应分支要求配置。编译 AOSP 也不是用 Android Studio 自带的 Gradle 去构建整棵源码树。
安装相关依赖
在本文选定的 Ubuntu 22.04 环境中,参考官方 Linux 依赖清单:
1 | sudo apt update |
这里修正了原文的 lib32z-dev,不再照搬旧 lib32ncurses5-dev 等包名。其他发行版或旧 Android 分支应使用自己的依赖清单,不能混装后假定结果相同。
下载 Pixel 的驱动
历史 Pixel 流程:专有硬件支持文件要与设备代号和 Android 构建号匹配。正式版本驱动下载页按设备与构建号列出文件;不能把旧 blobs-preview 页中的“最新预览驱动”与任意源码混用。按随包说明在对应源码根目录提取,并阅读许可条件;文件通常进入 vendor/。原文没有记录下载包的完整版本,因此不能据旧截图补造它的配套标签。
下面是当时的高通二进制提取结果:


本文的 Android 16 Cuttlefish 目标不使用这些 sailfish 二进制,无需下载旧 Pixel 驱动包。
编译 Pixel 的系统镜像
原来的 lunch 菜单和 make -j8 如下,图中选中的是 aosp_sailfish-userdebug,平台代号为开发中的 Q:


新增的 Android 16 Cuttlefish 示例,在同步完成的源码根目录、同一个 Bash 会话里执行:
1 | source build/envsetup.sh |
目标和参数按 android-16.0.0_r1 的 envsetup.sh核对:该版本已移除旧交互菜单,无参数 lunch 会报错;三段式是产品、release 配置、构建变体。aosp_current 在这个标签中映射到 bp2a,不是让源码自动追到今天的最新版本。userdebug 适合平台调试,量产 user 不能默认获得同样的调试权限。
m 是构建入口,-j8 表示最多 8 个并行任务,不是 CPU 必须有 8 个线程;内存不足时要降低并发。不要根据一张进度截图认定整个构建已经成功。
编译成功
以构建进程成功退出为前提,再查看 $ANDROID_PRODUCT_OUT 中本次目标的镜像。只看到 out/ 里有文件,不能排除上次构建遗留的产物。下面仍是原来的 out/target/product/sailfish,不是新增 Cuttlefish 的输出:

要运行本地 Cuttlefish 构建,先完成官方主机准备步骤:KVM 可用,安装 Cuttlefish 主机包,并使用户组/udev 设置生效。在完成构建并保留上述 envsetup/lunch 环境的终端中启动:
1 | launch_cvd --daemon |
如果改用 CI 下载包,镜像与 cvd-host_package.tar.gz 必须来自同一个 build,不能拿最新 host 包随意配旧镜像。需要检查虚拟设备是否实际启动、能通过 ADB 连接,以及修改后的功能是否生效;编译通过不等于运行通过。
刷机
此节仅用于已有匹配设备源码、专有文件和镜像的真机目标。上面的 Cuttlefish 镜像不能刷进 Pixel。 原文漏掉了设备解锁和数据处理前提。
先备份数据,确认设备允许 OEM 解锁、USB 调试已授权、源码产品与真机匹配,再按官方 Fastboot 流程进入 bootloader。需要解锁的设备通常要在机身确认;解锁会清除用户数据,不能当作普通重启。解锁方式仍以具体机型为准。
原图中的 fastboot devices 只证明当时工具识别到了设备:

在正确 lunch 目标的构建环境中,原文使用的是:
1 | fastboot flashall |
官方首次完整刷入示例使用 fastboot flashall -w,其中 -w 会擦除 /data。原命令不带 -w,但这不保证跨版本数据兼容,更不保证解锁或其他刷机步骤不会清数据。不要把擦除参数隐藏在“一键命令”里,也不要将不同机型/构建的分区文件混刷。

这张图证明的是当次命令的写入结果,没有系统启动完成或功能测试的证据。现代设备的动态分区、fastbootd、AVB 和 A/B 槽位也要按目标设备流程处理,不能照抄旧图中的分区列表。
修改和编译 Framework 、Service、Res
先完成同一源码树、同一目标的完整构建,再做增量修改。目录名不等于模块名,模块编译完成也不一定已经生成可刷镜像。
修改代码 IDE
java代码
Java/Kotlin 可以用 Android Studio 编辑。整棵 AOSP 不是普通 Gradle 项目,代码索引和依赖可参考分支中的 AIDEGen或该分支支持的 IDE 工程生成方式;编辑器能打开文件不代表能正确解析所有平台符号。
c/cpp代码
C/C++ 可继续用熟悉的编辑器,如 VS Code。Source Insight、Eclipse 是原文当时的选择,不是系统构建要求;补全和跳转需要与实际编译配置匹配。
编译 Framework
原文 mmm framework/base 少了一个 s。旧分支的目录构建应写作 mmm frameworks/base,但不要把这个旧入口直接套到 Android 16。本文标签中用于安装的非 APEX framework 模块是:
1 | m framework-minus-apex |
Android 16 的模块定义说明,它安装时文件名为 framework;另一个名为 framework 的模块是 build-only,不能因为名字相同就把产物当成可部署的 jar。位于 APEX 的代码需构建其所属模块。
编译 Services
原文旧目录入口是 mmm frameworks/base/services。本文 Android 16 标签提供名为 services 的可安装模块:
1 | m services |
编译 res
原文旧目录入口是 mmm frameworks/base/core/res。对应现代模块示例是:
1 | m framework-res |
API、资源 ID、bootclasspath、APEX 或跨分区接口发生变化时,应重建依赖和完整镜像,再验证启动与对应功能;不能只替换单个文件就判定完成。
root && remount
下面是历史 userdebug 设备的成功输出,不能套到普通量产 user 系统。Bootloader 解锁也不等于 adb root 一定可用:

Android 16 的调试构建可能通过 OverlayFS 提供可写层。同版本 remount 说明给出了 verity、重启和挂载顺序。仅在自己的测试设备/虚拟设备上、明确允许修改系统分区的调试环境中逐步执行:
1 | adb root |
-R 可能安排必要的 verity 状态变更和重启;这些是调试配置,不是量产使用建议。若任一步失败,先处理权限、构建类型或设备支持问题,不要继续假定分区已可写。
push
adb sync system 同步当前构建输出的 system 文件,不能保证其他分区、APEX、boot 镜像或预优化产物都更新了。对同一构建上的兼容 system 文件小改动,可参考分步流程:
1 | adb shell stop |
每步检查结果;同步失败时应先恢复已停止的 Android 服务(adb shell start)并处理错误,不能把失败当更新成功。这里的 stop/start 控制 Android 服务,不是退出再打开终端 shell。涉及初始化、bootclasspath 或其他分区的变化时,应按完整重建/部署流程处理。
重启后检查实际文件或版本标记,并运行相关功能验证。OverlayFS 覆盖层与 OTA 更新存在限制,刷回镜像后也要确认没有残留覆盖;“命令返回成功”只是一部分证据。
关于我 && 博客
下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!
- 博主个人介绍 :里面有个人的微信和微信群链接。
- 本博客内容导航 :个人博客内容的一个导航。
- 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
- Android性能优化知识星球:付费社群已于 2026 年停止运营,不再招收新成员;此处保留历史介绍。
一个人可以走的更快 , 一群人可以走的更远
