如何排查 WMS 问题
2026/8/6大约 3 分钟WMS 窗口生命周期Android 14dumpsys windowdumpsys inputWindowState
如何排查 WMS 问题
黑屏、窗口错位、无焦点和不能点击分别可能停在创建、布局、Surface/Buffer、可见性、焦点或 输入阶段。先用 dump 保存当前状态,再用日志和 trace 还原状态变化;只搜索一条错误日志, 很容易把后续症状当成根因。
当前状态与历史时序要一起看
| 常见误解 | 正确理解 |
|---|---|
| 先查日志就能定位窗口问题 | 窗口问题先查“当前状态”(dump),再用日志补“历史时序” |
dumpsys window 没有目标窗口 = 窗口不存在 | 厂商字段过滤可能漏掉名称,结论需要多命令交叉验证 |
排障的关键不是记忆更多命令,而是按生命周期阶段逐层排除:先把现象翻译成“哪个阶段出了问题”,再去对应模块取证据。
统一诊断链
逐步解释:
- ① WindowState:
dumpsys window windows找目标窗口记录。 - ② frame:对比布局结果与应用期望,错位问题在此暴露。
- ③ Surface/Buffer:
dumpsys SurfaceFlinger --list看 Layer 是否创建。 - ④ visible:确认窗口逻辑可见性是否成立。
- ⑤ focus:
dumpsys window的焦点字段是否指向预期窗口。 - ⑥ input target:
dumpsys input检查输入目标与可触摸区域。
症状矩阵
| 现象 | 第一证据 | 生命周期阶段 | 责任层 | 下一步验证 |
|---|---|---|---|---|
| 窗口没出现 | dumpsys window windows | 创建/接纳 | WMS | 查看 addWindow 失败日志与 token |
| 黑屏但窗口存在 | dumpsys SurfaceFlinger --list | Surface/Buffer | WMS + 应用 + SurfaceFlinger | 检查 Layer、Buffer 与合成状态 |
| 错位/顶栏 | window frame 与 InsetsState | 布局 | WMS Policy | 对比应用请求与最终 frame |
| 无焦点 | dumpsys window focus 字段 | 焦点 | WMS | 检查可聚焦标志与焦点候选 |
| 输入法不跟随 | IME target 字段 | 焦点/输入 | WMS + IME | 检查 computeImeTarget 结果 |
| 不能点击 | dumpsys input 命中结果 | 输入 | WMS + InputDispatcher | 检查 TouchableRegion 与遮挡 |
常用命令
环境:主机终端连接调试设备,目标窗口保持在可观察状态。以下命令的字段可能因厂商实现不同而变化:
adb shell dumpsys window windows
adb shell dumpsys window displays
adb shell dumpsys SurfaceFlinger --list
adb shell dumpsys input| 命令 | 观察维度 | 注意 |
|---|---|---|
dumpsys window windows | WindowState、frame、可见性、焦点 | 字段可能被过滤 |
dumpsys window displays | 显示器与容器层级 | 多屏问题先看这里 |
dumpsys SurfaceFlinger --list | Layer 是否存在 | 与 WindowState 数量不一一对应 |
dumpsys input | 焦点与输入窗口信息 | 与 window dump 交叉验证 |
单一 dump 缺少某个名称不能证明对象不存在;先用状态确认“现在是什么”,再用 logcat 确认“之前发生了什么”。
源码入口
源码基准:android-14.0.0_r75。
以下文件默认位于 frameworks/base/services/core/java/com/android/server/wm/,表中省略该前缀:
| 文件 | 关键位置 | 作用 |
|---|---|---|
WindowManagerService.java | dump()(dumpsys window) | 窗口状态证据入口 |
DisplayContent.java | 3687-3742 行焦点与窗口 dump 字段 | 焦点与层级状态 |
InputMonitor.java | 333 行 updateInputWindowsLw() | 输入窗口信息状态 |
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp | 1355 行 findTouchedWindowAtLocked() | 命中测试逻辑 |
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp | 5903 行 createLayer() | Layer 状态入口 |