Android 窗口系统阻塞复现检查
结论
已复现同类系统窗口阻塞。 等搜索测试结束后,独占设备复测在第 17 轮重启时触发。
新的系统转储再次显示任务快照调用 captureLayersSync,窗口管理锁被占用,
窗口、显示、动画线程阻塞 60 秒,随后 watchdog 终止 system_server。
这是本次独占测试 17 次尝试中的一次故障,不能据此估计稳定发生概率。 未完成原计划的 60 轮;确认同类故障后停止注入并保存证据。
后续频率复测另做 3 批,共 73 次尝试,没有再次出现目标 watchdog,详见下一节。
后续复现频率检查
2026-10-25 10:30:13–10:43:16(Asia/Shanghai)执行 3 批测试,原计划每批最多 30 轮。 每批从同一 AVD 冷启动,使用上面记录的同一 APK,操作顺序和等待间隔保持一致。 不输入或保存笔记,不重装 APK,不调整 GPU 配置,也不运行其他设备测试。
| 批次 | 尝试轮数 | 完整通过 | 目标系统 watchdog | 其他中断 |
|---|---|---|---|---|
| 1 | 13 | 12 | 0 | 第 13 轮重启后,编辑模式恢复等待超过 25 秒 |
| 2 | 30 | 30 | 0 | 无 |
| 3 | 30 | 30 | 0 | 无 |
| 本次合计 | 73 | 72 | 0 | 1 次恢复等待超时 |
- 本次目标异常的观测计数为 0 / 73 次尝试,0 / 3 批;不能解释为不会再发生。
- 若与前面的独占复现合计,则为 1 / 90 次尝试(约 1.1%),4 批中 1 批发生。
- 这只是已观察到的次数比例,不是稳定故障概率。
- 前次复现开始时模拟器已运行较久,本次各批冷启动,运行时长和缓存状态不同。
- 批内循环并非独立随机样本,第一批又因另一类异常提前停止,不据此计算置信区间。
- 两批各 30 轮未触发,说明不能将前次第 17 轮当作固定触发阈值。
- 72 个完整轮次的重启后界面树读取最大耗时 3.8375 秒,完整流程最大耗时 15.0879 秒。
- 72 个完整轮次都核对编辑器全文和磁盘文件与原基线一致。
- 测试结束后另冷启动一次模拟器,恢复核对通过:正文 1,159 字符、磁盘文件 1,118 字节与原基线一致, 安装包 SHA-256 未变;结束时应用可正常使用。
第一批的独立等待超时
- 第 13 轮的
am force-stop在 10:31:58.747 发起,随后立即am start。 - 25 秒内界面树未出现选中的“编辑”节点,脚本停止该批,保留原始 XML。
- XML 中无法读取到应用的笔记控件;没有足够证据将其直接认定为应用启动死锁。
- 脚本退出后继续保留约 90 秒系统诊断窗口,没有目标
WATCHDOG KILLING SYSTEM PROCESS。 dumpsys window正常返回;dumpsys activity lastanr为<no ANR has occurred since boot>。- 没有新增
/data/anr/转储,未见与前次相同的系统 watchdog 证据。 - 此轮计入尝试总数,单独报告为恢复等待超时,不计为目标窗口阻塞,也不计为完整通过。
- 更早的准备阶段曾因冷启动恢复为预览模式而等待编辑模式超时,尚未进入循环,未计入上述 73 轮。
- 准备步骤改为显式切到编辑模式;循环内不更改等待间隔或补点按钮。
频率检查证据
- 提交保留的频率汇总包含逐批结果和恢复核对。
- 临时脚本:
build/qa-window-repro/frequency.py,复用项目test/ui/driver.py。 - 原始目录:
build/qa-window-repro/frequency/。batch-1/至batch-3/:status.json、actions.jsonl、console.txt、logcat.txt、restart-*.xml。- 第一批另有
window-timeout.txt、lastanr-timeout.txt和后续窗口/ANR 记录。 - 三批日志均未出现
Unexpected EOF,采集窗口内未检出目标 watchdog,未生成新的 ANR 转储。 summary.json:最终汇总;recovery/:最后一次冷启动后的实际界面和核对日志。analyze.txt、flutter-test.txt:频率检查结束后执行的验证,避免增加设备测试期间的宿主负载。
- 只覆盖当前 Debug 模拟器及这条重启流程;没有重跑整小时混合随机操作或真机测试。
独占设备复测
- 另一项搜索测试进程结束后开始,操作时间为 Asia/Shanghai。
- 固定 APK SHA-256:
BD5CE1D0A10A6518E25D53F986AAF77A8E9BFF06D315E5D4381387501B1C83E3。- 为包含搜索修复的新安装包,与 10 月 24 日报告的 APK 不同。
- 测试前包记录
lastUpdateTime=2026-10-25 02:06:49(UTC),期间本次没有安装操作。
- 独占测试使用同一 AVD、测试库和下文的前后台切换/重启流程。
- 前 16 轮完整通过,每轮编辑器全文和磁盘内容与基线一致。
- 第 17 轮:
- 10:12:53.812:按 HOME。
- 10:12:54.376:
am start返回应用,10:12:56.471 的界面树读取仅 0.0765 秒。 - 10:12:57.765:
am force-stop;10:12:57.819 紧接着am start。 - 此后未取得恢复为编辑模式的记录,测试 RPC 未正常完成。
- 10:13:16.558:
WAITED_UNTIL_PRE_WATCHDOG。 - 10:14:09.860:
WATCHDOG KILLING SYSTEM PROCESS,报告三个系统线程阻塞 60 秒。 - 原
system_serverPID 为 587,后续 PID 为 6890;系统服务随后仍未恢复。
- 新转储的关键链路与原故障一致:
android.anim持有WindowManagerGlobalLock,位于任务快照的captureLayersSync。watchdog.monitor、android.display等线程等待该锁。- SurfaceFlinger 主线程等待
BpComposerClient::executeCommands。
- 故障后
dumpsys dropbox返回Can't find service: dropbox,截图命令设置 8 秒超时后未生成图片。 - 完整保存新 watchdog / pre-watchdog 原始转储后,主动停止本次测试进程并重启模拟器恢复环境。
- 通过
adb root读取只允许系统账户访问的/data/anr/,未修改设备数据或图形配置。 adb reboot后仍等待 SurfaceFlinger 服务;adb emu kill未能关闭宿主进程。- 最终停止该 AVD 的宿主进程,用
-avd t1 -no-snapshot-load冷启动,未清除数据或更改 GPU 配置。 - 模拟器启动完成后重新启动应用,恢复核对通过:编辑器全文 1,159 字符与故障前相同, 磁盘文件 1,118 字节与重启前相同,APK SHA-256 未改变。
- 通过
提交保留的关键证据:watchdog 日志与系统线程栈。
完整原始证据位于 build/qa-window-repro/exclusive/:
actions.jsonl、console.txt:逐轮时序及 16 轮通过记录。logcat.txt:本次系统 watchdog 及system_server重启过程。pre-watchdog-anr.txt:10:13:16 的预警转储。watchdog-anr.txt:10:14:01 开始收集的 60 秒阻塞转储。recovery-pre-watchdog-anr.txt:新系统进程仍阻塞的后续转储。recovery-checks.json、recovery-final/:完整重启模拟器后的正文、磁盘和安装包核对。
首次受干扰的尝试
首次尝试未复现原报告中的 89.50 秒窗口阻塞,但存在并行设备操作,不能判定问题已排除。 共完成 7 轮“前后台切换 → 强制停止并立即启动”,第 8 轮期间主动停止本次测试进程以避免干扰另一项测试。
- 第 1、2 轮完成时未发现 APK 重装,重启后界面树读取分别为 4.7697 秒和 5.1223 秒。
- 第 3 轮期间,另一项搜索修复测试在同一设备重装 APK,并操作应用。
- Android 包记录的
lastUpdateTime从2026-10-24 13:45:57变为2026-10-25 02:06:49。 - 包记录使用 Android 系统时间 UTC;对应本地时间为 10:06:49。
- 第 3–7 轮受环境干扰,不能视为固定 APK、独占设备条件下的复测结果。
- Android 包记录的
- 7 轮均核对编辑器全文和测试笔记磁盘内容不变。
- 7 轮重启后的单次界面树读取最大耗时为 5.1651 秒;完整工作流最大耗时为 32.5991 秒。
- 完整工作流还包含前后台切换、启动等待、截图和内容核对,不等同于窗口阻塞时长。
- 停止后与测试前相比,没有新增
system_server_pre_watchdog或system_server_watchdog条目。 dumpsys activity lastanr返回<no ANR has occurred since boot>。
该阶段单独保留,不计入上面的独占测试结果。 原始报告:一小时深入随机模拟器测试。
环境与操作
- 设备:
emulator-5554,AVDt1,Android 15 / API 35,x86_64。 - 系统指纹与原报告一致:
Android/sdk_phone64_x86_64/emu64x:15/AE3A.240806.019/12368160:userdebug/test-keys。 - 复用原测试库
b2f67a42f3a58ae388c95efbf5a8740a的preview.md,切到编辑模式。 - 每轮按 HOME,等待 500 ms,执行
am start,等待编辑模式恢复,再等待 1 秒。 - 执行
am force-stop,紧接着am start,通过 uiautomator2 读取界面树并等待编辑模式恢复。 - 每轮核对编辑器完整正文及
run-as读取的已保存文件。 - 首次尝试未输入或保存笔记、清除应用数据、构建安装 APK 或重启模拟器。
- 测试期间发生的 APK 安装来自另一项搜索修复测试。
- 本次测试首条完成记录为 10:06:17;操作记录使用 Asia/Shanghai。
原始故障转储复核
复核 build/qa-hour/system-pre-watchdog.txt 后,原报告中的系统阻塞判断仍有依据:
android.anim持有WindowManagerGlobalLock,调用任务快照的TaskSnapshotController.recordSnapshot。- 该线程在
BpSurfaceComposer::captureLayersSync中等待 Binder 返回。 watchdog.monitor和android.display等线程等待同一窗口管理锁。- SurfaceFlinger 的截图 Binder 线程等待主线程提供显示和图层快照。
- SurfaceFlinger 主线程位于
presentAndGetReleaseFences→BpComposerClient::executeCommands。
据此可推断阻塞链路延伸到模拟器显示合成服务,不能归为普通 Dart 异常。 现有栈只说明等待关系,不能确定图形服务、宿主 GPU 或其他环节中的最终根因。
验证与证据
flutter analyze:1 条既有 info,test/mp3_refresh_view_test.dart:37:11缺少花括号。flutter test:379 项通过。- 静态及单元测试检查了当时工作区,也包含另一项搜索修复的未提交改动;不代表安装包验证。
- 检查在设备测试初期并行运行,对宿主负载可能有影响。
- 临时复现脚本及逐轮记录:
build/qa-window-repro/repro.py、actions.jsonl、console.txt。 - 系统记录:
dropbox-before.txt、dropbox-paused.txt、lastanr-before.txt、lastanr-paused.txt。 - 界面树:同目录
restart-*.xml;静态和单元检查输出:analyze.txt、flutter-test.txt。 logcat.txt在 APK 重装时段出现Unexpected EOF,日志流不完整;未以此证明全程无异常。- 以上原始文件位于忽略的
build/下;flutter clean会删除,本次没有执行清理。
同一环境重复前后台切换并立即重启可以再次触发,但尚不能保证第几次发生。 本轮没有重跑完整一小时随机序列,也未覆盖真机或其他 Android 系统版本,未修复图形链路根因。
