Android冻屏

adb shell dumpsys window windows > window.txt

过滤 has_drawn

mDrawState 是 Android 窗口管理服务(WMS)中,用来描述窗口绘制状态的关键变量,它有几个典型值:

  • NO_SURFACE:窗口还没有创建 Surface
  • COMMIT_DRAW_PENDING:窗口绘制请求已提交,但还没完成
  • READY_TO_SHOW:绘制已提交,Surface 还没显示
  • HAS_DRAWN :窗口首次绘制完成,且内容已经成功上屏显示,处于稳定可见状态

窗口还没画出来(HAS_DRAWN 状态为 false)

窗口已经画出来了(HAS_DRAWN 状态为 true)

怎么看哪个窗口在最顶端

字段 含义 作用
layer 窗口的 Z 轴层级值 越大越靠上,同一屏幕上层级最高的窗口就是最顶端的
type 窗口类型(Window Type) 系统窗口(如悬浮窗、系统弹窗)默认层级高于普通应用窗口
isOnScreen / visible 窗口是否可见且在屏幕上 只有同时为 true 的窗口,才会实际参与显示层级排序

二、结合你的日志,教你一步步定位最顶端窗口

我们用你截图里的日志举例,手把手拆解:

1. 先看 layer 值:谁的数字大,谁就在最上面

你日志里的这一行:

Surface: shown=true layer=0 alpha=1.0 rect=(0.0,0.0) transform=(1.0, 0.0, 0.0, 0.0, 1.0)

规则:

  • 日志里所有窗口的 layer 值,数值越大,Z 轴越靠上,显示优先级越高。
  • 比如 A 窗口 layer=10,B 窗口 layer=5,那么 A 窗口一定在 B 窗口的上面。

注意:部分日志会用负数表示层级(比如 layer=-1 表示在底层),但核心逻辑不变:数值越大越靠上。

2. 再看窗口类型 type:特殊窗口天生优先级更高

你日志里的关键信息:

这里的 ty=APPLICATION_OVERLAY(即 TYPE_APPLICATION_OVERLAY)是悬浮窗 / 系统覆盖窗口类型 ,它的层级天生就高于普通的 APPLICATION 类型窗口,哪怕 layer 值看起来不大,也会盖在普通应用窗口上面。

常见窗口类型优先级(从高到低):

  1. 系统级窗口(如状态栏、系统弹窗、Toast)
  2. APPLICATION_OVERLAY 悬浮窗 / 系统警告窗口
  3. 普通应用的 Activity 窗口
  4. 应用内部的 Dialog/Toast

3. 排除不可见窗口:只看 shown=true + isOnScreen=true 的

日志里这两个字段:

cpp 复制代码
Surface: shown=true
isOnScreen=true
isVisible=true

三、给你一个通用的排查步骤

  1. 过滤有效窗口 :先筛出所有 shown=true、isOnScreen=true、isVisible=true 的窗口,排除不可见的。
  2. 按 layer 排序 :把这些窗口按 layer 值从大到小排序,第一个就是当前层级最高的窗口。
  3. 结合窗口类型二次确认 :如果有 APPLICATION_OVERLAY、系统窗口类型,优先级默认高于普通应用窗口,哪怕 layer 值相同,也会盖在上面。
  4. 看 zOrder 字段(部分日志有) :部分 WMS 日志会直接输出 zOrder,值越大越靠上,直接看最大值即可。

还可以看

adb shell dumpsys SurfaceFlinger > Surface

过滤 focesed

一、先搞懂 dumpsys SurfaceFlinger 输出的核心结构

这个命令输出的日志,核心是SurfaceFlinger(Android 的屏幕合成服务)当前的图层列表,决定了屏幕上每个窗口的绘制顺序和最终显示效果。

关键信息分为两部分:

  1. 图层列表(Layers):每个 Surface(窗口)的层级、状态、大小、透明度
  2. 合成状态:是否在刷新、是否合成成功,直接关联冻屏问题

二、结合你的日志,手把手分析

你的截图里就是典型的 SurfaceFlinger 图层列表,我们一行行拆解:

1. 每一行代表一个图层(Surface)

格式是固定的:rel 0 | [PID] | CLIENT | 0 | [视口/大小] | [位置/透明度] | [标记]

举你日志里的例子:

cpp 复制代码
com.android.launcher3/...QuickstepLauncher#363
rel 0 | 1 | CLIENT | 0 | 0 1440 2960 | 0.0 0.0 1440.0 2960.0 | []
  • com.android.launcher3/...:图层所属的包名 / 窗口,这里是桌面 Launcher
  • #363:图层的唯一 ID,后续可以用它关联 WMS 日志
  • rel 0:相对层级(rel = relative z-order),数字越大越靠上
  • 1:进程 PID,Launcher 的进程号是 1(system_server 进程)
  • 0 1440 2960:图层的大小,这里是 1440×2960(全屏桌面)
  • 0.0 0.0 1440.0 2960.0:图层在屏幕上的位置(从 (0,0) 到 (1440,2960),全屏)
  • []:图层标记,空表示正常,[*] 表示该图层是当前的 "脏区域"(需要刷新)

2. 关键判断点:谁在最顶端?

看两个核心字段:

(1)rel(相对层级)

rel 就是图层的 Z 轴顺序,数值越大,越靠上。你日志里的图层:

  • Launcher:rel 0
  • 你的 App Sys2038:com.example.mysystemdialog.MainActivity#361:rel 0
  • 你的 App Sys2038:com.example.mysystemdialog.MainActivity#372:rel 0
  • 状态栏 StatusBar#80:rel 0
  • 导航栏 NavigationBar0#73:rel 0

⚠️ 这里的 rel 0 不代表层级相同,因为 dumpsys SurfaceFlinger 输出的图层列表是从上到下排序的!

  • 日志里越靠下的行,层级越高,越在屏幕上方。
  • 你日志里的顺序:Launcher → App#361 → App#372 → StatusBar → NavigationBar所以层级从低到高是:Launcher < App#361 < App#372 < StatusBar < NavigationBar也就是NavigationBar(导航栏)在最顶端,其次是状态栏,然后是你的两个 App 窗口。
(2)[*] 标记

你日志里 App#372 这一行:

这里的 [*] 表示:这个图层是当前需要刷新的脏区域 ,也就是 SurfaceFlinger 正在处理的图层。如果冻屏时,只有这个图层一直带 [*] 但没有后续刷新,说明:

  • 你的 App 提交了刷新请求,但 SurfaceFlinger 没有合成成功,或者 App 没有继续提交新的帧。

3. 结合冻屏问题,重点看这几个状态

(1)图层是否存在且显示
  • 如果你的 App 图层不在列表里,说明窗口已经被销毁,冻屏和它无关。
  • 如果图层存在,但 alpha=0 或 visible=false(部分版本日志会显示),说明窗口被隐藏,也不会导致冻屏。
(2)是否有新的帧提交

正常情况下,SurfaceFlinger 每 16ms 会刷新一次图层列表。如果冻屏时,你的 App 图层的位置、大小、标记一直不变,说明:

  • App 主线程阻塞,无法生成新的帧
  • App 的 Surface 被意外销毁,无法提交新的 Buffer
  • SurfaceFlinger 合成卡住,没有把新的帧刷到屏幕上

过滤掉 无法触摸页面

相关推荐
denlaku1 分钟前
JDK 12 新特性详解
java·开发语言
用户094248568035 分钟前
第28章:JDK容器感知、cgroup与云原生JVM参数治理
java·jvm
鬼手点金6 分钟前
opencode-全能开发者配置
java·linux·服务器·前端·javascript·学习·前向传播
Nebula_g6 分钟前
JavaSE拓展:可变参数
java·开发语言·算法·安全·javase·可变参数
念越24 分钟前
初中语数英答题与竞赛平台
java·数据库·spring boot
知守观28 分钟前
一个半天需求干了三天:代码腐化的五个信号与自查命令
java·后端·代码规范
代码山河43 分钟前
Java学习路线图:2026年最新版,从入门到架构师
java·学习·架构·教程·面向对象·项目
anew___44 分钟前
《从零手写操作系统 (30):环境变量与进程上下文——export/unset与继承语义》
java·开发语言·网络·jvm·算法
jason成都1 小时前
rtklib_java项目新增模块:rtklib-research与rtklib-stream功能详解
java·gnss·rtklib·rtklib_java
我是场1 小时前
我的NPI项目之-Touch的EE特性
android·arm开发