AOSP Android 15 编译 Pixel 6 ROM:源码、内核与镜像集踩坑记录
目标:记录一次 Pixel 6 / Android 15 从系统源码、vendor blobs 到本地内核镜像集的完整构建过程。
这次做的不是“随便编一个 AOSP”,而是把 AOSP Android 15 + Pixel 6 vendor blobs + 本地编译的 GS101/raviole 6.1 内核 组合成一套一致的镜像集。重点是记录构建链路、版本选择和容易忽略的内核模块一致性问题。
最终结论先放前面:
- AOSP 目标:
aosp_oriole-bp1a-userdebug - AOSP tag:
android-15.0.0_r20 - Build ID:
BP1A.250305.019 - 设备:Pixel 6 /
oriole - 平台:GS101 /
raviole - 内核分支:
android-gs-raviole-6.1-android15-qpr2-beta - 内核版本:Linux
6.1.99 - 系统镜像构建成功
- 本地内核构建成功
- 本地内核已接入 AOSP 镜像生成
- 已修正
vendor_dlkm.img仍沿用官方预编译镜像的问题
这篇文章记录完整过程和踩坑点。
1. 为什么先做“干净基线”
在改系统或内核之前,建议先确认三件事:
1. Android 15 的 Pixel 6 产品目标能正常构建。 2. Pixel 6 对应的 6.1 内核能从源码构建。 3. AOSP 输出镜像里的 boot.img、vendor_boot.img、dtbo.img、vendor_dlkm.img 是同一套内核产物。
如果这一步没打通,后面任何启动失败、模块加载失败、SELinux 报错,都很难判断是“基础环境问题”还是“后续改动问题”。
这样做的价值是把基础环境问题提前排除。后续如果出现启动失败、模块加载失败或 vendor 服务异常,才有明确的对照基线。
2. 版本选择
AOSP
android-15.0.0_r20
BP1A.250305.019
aosp_oriole-bp1a-userdebugPixel 6 vendor blobs
vendor 包安装到:
~/Android_SRC/aosp/vendor/google_devices/oriole对应版本:
BP1A.250305.019Kernel
Pixel 6 当前手机上原系统是 Android 13 时代的 5.10 内核:
Linux localhost 5.10.177-android13-4-00003-ga7208022a7ea-ab10815828但目标系统是 Android 15,所以没有继续沿用 5.10,而是选择 Google 官方的 raviole 6.1 分支:
android-gs-raviole-6.1-android15-qpr2-beta这个分支不是单纯 GKI,它包含 GS101、raviole/oriole 设备树和配套模块,适合 Pixel 6 / Pixel 6 Pro。
3. AOSP Pixel 6 基线构建
构建命令:
source build/envsetup.sh
lunch aosp_oriole-bp1a-userdebug
m -j12 droid首次完整构建结果:
#### build completed successfully (01:35:02 (hh:mm:ss)) ####输出目录:
~/Android_SRC/aosp/out/target/product/oriole关键镜像包括:
boot.img
vendor_boot.img
dtbo.img
dtb.img
system.img
system_ext.img
product.img
vendor.img
vendor_dlkm.img
vbmeta.img
vbmeta_system.img
bootloader.img
radio.img到这里,只能说明 AOSP + vendor blobs 的 Pixel 6 产品目标能构建,还不能说明本地内核已经接入。
4. Pixel 6 6.1 内核构建
内核源码目录:
~/Android_SRC/pixel_kernel稳定可用的构建命令:
tools/bazel --batch run \
--config=stamp \
--config=raviole \
--config=no_download_gki \
--config=no_download_gki_fips140 \
--kernel_package=@//aosp \
//private/devices/google/raviole:gs101_raviole_dist这里有一个 WSL 相关坑:Bazel 常驻 server 模式会触发 Netty / event loop 相关异常。使用 --batch 可以稳定绕过。
内核 dist 输出:
~/Android_SRC/pixel_kernel/out/raviole/dist关键产物:
Image.lz4
boot.img
dtbo.img
vendor_dlkm.img
modules.load
vendor_dlkm.modules.load
vendor_dlkm.modules.blocklist
*.ko本次内核构建完成 567 个 action,耗时约 11 分 42 秒。
5. 接入本地内核时遇到的第一个坑
AOSP 的 device/google/gs101/BoardConfig-common.mk 会通过 TARGET_KERNEL_DIR 读取内核产物。
一开始直接这样做:
TARGET_KERNEL_DIR=/home/tower/Android_SRC/pixel_kernel/out/raviole/dist m -j12 droid结果失败。原因是 Soong 不接受源码树外部路径:
Path is outside directory解决方式是把内核 dist 放到 AOSP 树内:
mkdir -p ~/Android_SRC/aosp/device/google/raviole-kernels/local-dist
cp -a ~/Android_SRC/pixel_kernel/out/raviole/dist/. \
~/Android_SRC/aosp/device/google/raviole-kernels/local-dist/然后使用相对路径构建:
source build/envsetup.sh
lunch aosp_oriole-bp1a-userdebug
TARGET_KERNEL_DIR=device/google/raviole-kernels/local-dist \
m -j12 droid结果:
#### build completed successfully (21:24 (mm:ss)) ####日志里 boot.img 的 kernel size 是:
kernel_size: 16481167本地 Image.lz4 大小也是 16481167,说明 boot.img 已经确实使用本地内核。
6. 最关键的坑:vendor_dlkm.img 没有自动切换
第一次集成本地内核后检查产物时间戳,发现一个危险现象:
boot.img刷新了dtbo.img刷新了vendor_boot.img刷新了vendor_dlkm.img没刷新
这意味着系统可能变成:
boot.img:本地内核
vendor_dlkm.img:官方 vendor 包里的旧模块镜像这类不一致非常危险。内核能启动,不代表模块一定匹配;后续出现模块加载失败、驱动异常、设备功能异常时会很难排查。
原因在:
vendor/google_devices/oriole/BoardConfigPartial.mk原始逻辑:
BOARD_PREBUILT_VENDOR_DLKMIMAGE := vendor/google_devices/oriole/proprietary/vendor_dlkm.img也就是说,官方 vendor 包强制指定了预编译 vendor_dlkm.img。
修正为:
ifneq (,$(wildcard $(TARGET_KERNEL_DIR)/vendor_dlkm.img))
BOARD_PREBUILT_VENDOR_DLKMIMAGE := $(TARGET_KERNEL_DIR)/vendor_dlkm.img
else
BOARD_PREBUILT_VENDOR_DLKMIMAGE := vendor/google_devices/oriole/proprietary/vendor_dlkm.img
endif修正后重跑增量构建:
#### build completed successfully (11:22 (mm:ss)) ####日志中能看到:
Copy: out/target/product/oriole/vendor_dlkm.img最终哈希确认:
b5766a77c801ac8fdb58f7361ffcf57cec32a9e729655304681f7568cbe98e17 out/target/product/oriole/vendor_dlkm.img
b5766a77c801ac8fdb58f7361ffcf57cec32a9e729655304681f7568cbe98e17 device/google/raviole-kernels/local-dist/vendor_dlkm.img到这里,才能说本地内核和模块镜像已经成套接入。
7. WSL 环境下的几个经验
7.1 自动睡眠会让构建“慢得离谱”
之前出现过五小时只编译到约 60% 的情况,后面判断主要原因是 Windows/WSL 自动睡眠。
AOSP 构建期间 CPU 高负载是正常的,但系统睡眠会让构建进程暂停,甚至引入时间戳异常。
建议:
- 构建前关闭自动睡眠
- 接电
- 开高性能模式
- 不要把构建会话误认为“后台任务”
7.2 Missing restat 不一定是失败
WSL 下出现过:
ninja: Missing `restat`? An output file is older than the most recent input这通常和 WSL / Windows 时间戳偏差有关。只要最后没有 FAILED:,并且出现:
#### build completed successfully ####就先不要把它当成阻塞问题。
7.3 CPU 比内存更容易成为瓶颈
机器配置:
AMD Ryzen 7 8845H
64 GB RAM实际观察是 CPU 更容易吃满,内存没有明显瓶颈。m -j12 能跑,但温度会长期在 80 到 85 摄氏度附近。
如果想降低温度和噪音:
m -j8 droid代价是编译时间变长。
8. 刷机前检查
构建完成后,建议重点检查输出目录:
~/Android_SRC/aosp/out/target/product/oriole关键日志:
~/Android_SRC/aosp/build-oriole-bp1a-first.log
~/Android_SRC/aosp/build-oriole-local-kernel.log
~/Android_SRC/pixel_kernel/build-raviole-first.log刷机前至少确认:
- bootloader 是否解锁
adb/fastboot是否识别- 当前 slot 是否记录
- 是否有回滚方案
- 刷入完整镜像集,不只刷
boot.img
首次启动后验证:
uname -avendor_dlkm模块加载- 显示
- 触控
- Wi-Fi / 蓝牙
- 相机
- 基带
- vendor service
simpleperf cs-etm是否能产生非空 AUX 数据
结论
这次最大的经验是:不要只看 boot.img 是否换成了本地内核。
Pixel 6 这类设备上,vendor_boot.img、dtbo.img、vendor_dlkm.img 和 AVB 元数据都要作为一套整体看。尤其是 vendor_dlkm.img,如果仍然来自官方 vendor 预编译镜像,后续模块问题会很隐蔽。
完成这些检查后,再进入真机刷写和启动验证。