开发环境搭建:从源码下载到真机调试

说实话,SystemUI 调试的门槛不低,但环境搭好了,后面就顺了。我用过的方案有好几种,今天给你梳理一套我验证过的流程——从 AOSP 源码下载开始,到编译 SystemUI 模块,再到模拟器和真机调试配置。

2.1 AOSP 源码下载——别踩 repo 的坑

AOSP 源码体积巨大,官方推荐用 repo 工具管理。但你想想看,几十个 Git 仓库并行拉取,网络稍不稳定就中断。我早期遇到过 repo sync 三天没跑完的情况……后来总结了一套稳一点的方案。

我的做法:不要直接用 repo sync -j8,先 repo sync -j1 拉下主要分支,再逐步增加并行数。设置 git config --global core.compression 0 可以避免某些解压崩溃。

具体步骤如下:

  1. 安装 repo 工具(确保 Python 3 环境)
  2. 创建工作目录,比如 ~/aosp
  3. 初始化 manifest:repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r35
  4. 开始同步:repo sync -c -j4 --no-tags

嗯,这里有个关键点:--no-tags 能省下不少时间。如果你只是编译 SystemUI,不需要看每个仓库的历史 tag。

硬盘空间警告:AOSP 完整源码 + 编译产物至少需要 200GB 空间。我建议预留 300GB 以上。用 df -h 先看看你的机器。

2.2 编译 SystemUI 模块——别整全量编译

全量编译 AOSP 动辄两小时,但咱们只关心 SystemUI。用 mmm 或 make SystemUI 可以单独编译这个模块。我个人习惯用 mmm,因为它精准定位目标目录。

先设置环境:

cd ~/aosp
source build/envsetup.sh
lunch aosp_cf_arm64_phone-userdebug

然后编译 SystemUI:

mmm frameworks/base/packages/SystemUI/

输出路径一般在 out/target/product/<设备名>/system/priv-app/SystemUI/。如果你想更快,可以只生成 SystemUI.apk:

make SystemUI -j$(nproc)
经验之谈:修改 Java/Kotlin 代码后,用 make SystemUI 通常两三分钟就好。但如果改了资源文件(比如 layouts),最好 make SystemUI 后 make SystemUI-res 或者直接 mmm 指定 -B 强制重新编译。

2.3 模拟器调试环境——快速迭代的利器

我调试 SystemUI 最常用的环境其实是模拟器。真机有锁屏、模拟器更灵活。Cuttlefish 虚拟设备是官方推荐方案。

启动模拟器前,先确保内核和 ramdisk 编译好:

make -j$(nproc)      # 首次需要全量编译(一次痛苦,后面爽)
cvd start            # 启动 Cuttlefish 设备

怎么把新编译的 SystemUI 推到模拟器里?用 adb install -r 最简单:

adb install -r out/target/product/vsoc_x86_64/system/priv-app/SystemUI/SystemUI.apk
adb shell am force-stop com.android.systemui
adb shell am start -n com.android.systemui/.SystemUIService

但注意:模拟器里的 SystemUI 是系统应用,直接 install 可能报 INSTALL_FAILED_UPDATE_INCOMPATIBLE。我遇到过这个问题,后来改用 adb push + 重启大法:

adb root
adb remount
adb push out/target/product/vsoc_x86_64/system/priv-app/SystemUI/SystemUI.apk /system/priv-app/SystemUI/
adb reboot
权限注意:真机 root 后 push 方式一样,但很多商业手机禁止 remount。模拟器就没这烦恼,所以我说它更适合前期调试。

2.4 真机调试环境——直面真实硬件

真机调试能发现模拟器重现不了的 bug,比如按键反馈、低内存状态下的 UI 闪烁。我用 Pixel 系列比较多,因为驱动开源,兼容性好。

真机需要先解锁 bootloader,刷入 userdebug 或 eng 版本的镜像。官方叫法是「刷入工厂镜像」:

fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash vendor vendor.img
fastboot reboot

刷完以后,用 adb 设备列表确认连接:

adb devices
# 看到 "device" 状态就对了

然后和模拟器一样,用 adb push 替换 SystemUI。这里有个坑:直接 push 后 SystemUI 会立即 crash,因为进程还在跑,文件被占用。我建议先杀掉进程再 push:

adb shell stop
adb push ... /system/priv-app/SystemUI/
adb shell start
关键指标:真机调试时,adb logcat -s SystemUI 是你最好的朋友。SystemUI 崩溃后,logcat 里通常有堆栈和错误码。比如 NullPointerException 或 RemoteException。

另外,真机上 userdebug 版本可以开 adb root,但有些厂商会限制。如果 root 失败,考虑用 adb unroot 再重新授权。

2.5 环境搭建总体流程(一张图看懂)

下面这张图总结了我推荐的从零到真机调试的完整路径。每个节点都标注了关键步骤和常见陷阱。

SystemUI 开发环境搭建流程 ① 下载 AOSP 源码 ② 编译 SystemUI 模块 ③ 模拟器调试 ④ 真机刷入 userdebug ⑤ 真机调试 SystemUI ⑥ 崩溃定位方法 常见陷阱与避坑指南 • 下载 AOSP 时网络中断:加 --depth=1 只拉最新代码,减小体积 • 编译 SystemUI 慢:先全量编译一次,之后只用 make SystemUI • 模拟器 push 失败:用 adb root & remount,别用 adb install • 真机 SystemUI 崩溃:先 adb shell stop 再 push,别硬来 • logcat 太多:过滤 SystemUI 标签 + 错误等级 💡 建议按 ①→②→③ 走模拟器调试,熟悉后再尝试 ④→⑤→⑥ 真机调试

2.6 开发环境快速参考表

组件 关键命令 常见问题 解决思路
AOSP 下载 repo sync -c -j4 --no-tags 网络超时 加 --depth=1 或换国内镜像
编译 SystemUI make SystemUI -j$(nproc) 资源未更新 先 make SystemUI-res
模拟器启动 cvd start 启动失败 检查内核是否编译,cvd reset
真机替换 SystemUI adb push + stop/start push 后崩溃 确保 adb root 并 stopping
查看崩溃日志 adb logcat -s SystemUI *:E 日志太多 加 | grep -E "Exception|Error"

个人忠告:别在第一次就追求完美。我刚开始也贪快,跳过模拟器直接上真机,结果刷了三次都没成功。后来老老实实按流程走,反而省了时间。

2.7 调试环境验证——先跑个 demo

环境搭完后,改一行代码试试。比如在 SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java 里加个 toast:

Toast.makeText(mContext, "Hello SystemUI", Toast.LENGTH_SHORT).show();

编译、push、重启 SystemUI。如果你能在状态栏上方看到这个 toast,说明环境通了一切顺利。如果看不到,先检查 logcat,八成是权限或路径问题了。