4、复现环境搭建

说实话,做 SystemUI 卡顿崩溃复现,最怕的就是环境不一致。你在模拟器上复现的问题,拿到真机上死活不出来;真机 root 完又各种报错——这种事我碰上过太多次了。所以这一章,我把环境搭建的五个关键点掰开揉碎讲清楚。你照着搭一遍,后面复现效率至少提升 50%。

复现环境搭建核心模块 Android 模拟器 真机 root 权限 刷机纯净系统 adb 无线调试 Logcat 日志持久化 复现环境就绪 提示:每个模块独立完成,但最终需要协同工作,缺一不可

4.1 Android 模拟器配置

我平时主要用 Google 官方的 AVD Manager,偶尔也用 Genymotion。模拟器的好处是快照恢复方便,不用每次从头拉起。

配置上,我最在意三点:

  • 镜像选择:一定要选 x86_64 的 Google APIs 或 Play Store 镜像。为什么?因为 SystemUI 很多行为依赖 Google 服务,你选一个非 Google 镜像,卡顿场景可能根本触发不了。
  • RAM 和存储:建议给 4GB RAM 起步,存储 8GB。模拟器太抠内存会导致 SystemUI 频繁 OOM,反而干扰排查。
  • 快照功能:每次配置好环境、装好测试 APK,立刻拍一个快照。我曾经因为忘记保存,重复刷机五六次才意识到——嗯,这时间白花了。

我的经验: 如果你要复现的是“低内存下 SystemUI 崩溃”,可以给模拟器只配 2GB RAM,然后用 adb shell am compat 模拟低内存条件。但正常场景还是 4GB 起步,否则模拟器自己就卡死了,你没法判断是 SystemUI 的问题还是模拟器的问题。

4.2 真机 root 权限获取

真机 root 是调试 SystemUI 的杀手锏。没有 root,你连系统级日志都抓不全,更别说看 battery_stats、window_state 这些关键数据。

我目前最推荐 Magisk。流程很简单:

  1. 解锁 Bootloader——不同厂商不同命令,Oppo 要申请深度测试,小米要绑定账号等 7 天。注意:解锁会清空数据,先备份。
  2. 刷第三方 recovery,比如 TWRP 或 OrangeFox。
  3. 在 recovery 里刷入 Magisk.zip,或者把 boot.img 提取出来用 Magisk Manager 修补后再 fastboot 刷回。

⚠ 避坑指南: 我曾经因为刷完 Magisk 之后忘记禁用 AVB(Android Verified Boot),结果每次开机都提示“设备已损坏”,SystemUI 卡在启动画面。解决方案很简单:刷完 Magisk 后用 fastboot flash vbmeta vbmeta.img --disable-verity --disable-verification。

root 成功后,记得安装 Root Explorer 或 MT管理器,方便直接查看 /data/system/ 下的 SystemUI 相关文件。我个人习惯用 ADB Shell 加 su 操作,更稳定。

4.3 刷机后的纯净系统

为什么强调“纯净”?厂商定制 ROM 里往往存在“防卡顿”黑名单、省电策略、权限冻结等机制,它们会干扰 SystemUI 的原始行为。你复现出来的卡顿,可能根本不是 SystemUI 自身的 bug,而是被 OEM 的优化策略误杀了。

所以我建议刷 AOSP 或 Pixel Experience 这类接近原生的系统。刷机步骤:

  • 下载对应机型的 factory image 或 GSI。
  • 用 fastboot -w flashall 刷入(会清数据)。
  • 刷完后不要恢复任何备份,直接装一个干净 SystemUI 测试 APK。

关键验证: 刷完纯净系统后,先用 adb shell dumpsys window displays 确认显示参数正常;再用 adb shell dumpsys activity processes 看看 SystemUI 进程是否存在、oom_adj 是多少。正常情况 SystemUI 的 oom_adj 应该在 -100 到 0 之间,如果 > 200,系统可能随时会杀掉它。

4.4 adb 无线调试

调试 SystemUI 时频繁拔插 USB 线真的很烦,尤其某些机器 USB 口接触不良,一断连 logcat 就断了。我强烈推荐 adb 无线调试。

两步搞定:

  1. 手机连 USB,执行 adb tcpip 5555(默认端口)。
  2. 拔掉 USB,执行 adb connect <手机IP>:5555。

小技巧: 在路由器里给手机绑定静态 IP,这样每次不用查 IP。我开发时写了个批处理脚本,一键连接:adb connect 192.168.1.100:5555。另外注意电脑和手机要在同一个网段,防火墙可能会拦截 5555 端口,记得放行。

我曾经因为公司 WiFi 有访问策略(客户端隔离),adb 无线连不上,折腾了半天才发现原来是网络限制。如果你在公司也遇到类似问题,可以试试手机开热点,电脑连手机热点——这是我当时的救命方案。

4.5 Logcat 日志持久化

SystemUI 的卡顿崩溃经常发生在你意想不到的时刻,比如正在划动通知栏时突然闪退。等你手忙脚乱拿起手机打开 logcat,关键信息已经没了。所以日志持久化必须做。

我常用的命令:

# 持续写入文件,支持自动过滤
adb logcat -v threadtime -b all > systemui_crash.log

# 对于 ANR 或死机场景,单独抓 bugreport
adb bugreport bugreport.zip

这里有几个关键点:

  • 缓冲区选择:SystemUI 崩溃一般看 -b main(应用日志)和 -b system(系统日志),如果怀疑是显示问题,再加 -b events。
  • 时间戳:-v threadtime 能同时显示线程名和时间,对关联 ANR 很有用。
  • 持久化场景:对于“几分钟后必崩”的问题,我通常让 logcat 跑在后台,用 nohup 或者写一个定时任务每 5 秒检查一次进程。

⚠ 注意: 日志文件会迅速膨胀,一个晚上可能生成 2-3GB。建议用 logcat -r 1024 -n 5 按大小轮转,或者用 grep 只保留 SystemUI 相关行:
adb logcat | grep -E "(SystemUI|ANR|traces)" > sys_filtered.log

另外,我个人习惯同时拍屏幕录像,方便事后对照日志定位用户操作。用 adb shell screenrecord /sdcard/record.mp4 --time-limit 30,简单有效。