外观
状态已变化,但画面冻结,怎样继续追?
标准回答
如果手势和业务状态都在继续,但画面停在旧内容,我会把问题转到帧的生产与展示链路。应用逻辑正常,并不能证明用户看到了新画面。
我先确认目标窗口和 displayId,避免分析了另一个屏幕或过渡图层。然后看 View 是否请求并完成更新、RenderThread 是否继续工作、目标 Surface 是否有新内容,以及 SurfaceFlinger 最终展示的是不是这个窗口。主线程空闲和 doFrame 有执行,都不足以说明后面的渲染和展示已经完成。
跨屏场景里,还会检查渲染目标是否已经交接、旧 Surface 引用是否仍被使用、尺寸与裁剪是否更新,以及快照层是否遮住了真实窗口。例如业务不断刷新,但输出仍指向旧目标,用户看到的就可能一直是新屏上的静态内容。这只是候选原因,需要用对应图层和帧的证据确认。
如果证据落在窗口交接,就修复目标更新、状态时序和资源清理;如果落在 GPU、缓冲区等待或合成侧,则携带同一时间线和帧信息联合定位。最后不仅看画面恢复,还要验证连续移屏、取消、返回和显示销毁,确保修复没有留下旧资源或新竞态。
关键机制
- 从目标窗口、displayId、图层和帧标识入手,对齐应用帧与展示时刻,避免看错屏幕或动画图层。
- 检查 Surface 生命周期、旧 Surface 引用、裁剪/尺寸、可见性和过渡快照是否仍覆盖真实内容;是否存在资源等待需要 Trace 佐证。
- 若证据指向切屏后的旧渲染目标或旧回调,修复方向是正确交接目标与会话;若是 GPU、合成或驱动问题,则携证据联合定位。
通俗例子
假设业务持续刷新到旧 Surface,新显示仍覆盖着静态快照,看起来像整页冻住。应验证输出目标和图层关系,而不是仅缩短主线程任务。
追问与回答
doFrame 正常为什么仍然会冻屏?
doFrame 说明应用侧某些帧调度工作在推进,但之后还有渲染、缓冲区提交、合成和展示。应用也可能每次都画出相同内容,或者把新内容提交到错误目标。因此我会把“有帧回调”“产生新内容”“新内容被展示”分成三个观测点,逐步确认它们是否属于同一个目标窗口和同一段操作。
怎样证明修复有效?
我会同时验证业务状态和实际画面推进,而不是只看日志恢复。相同场景下,输入后的状态变化、目标产帧和最终展示应该能对应起来。再覆盖重复移屏、动画取消、返回、前后台切换和显示销毁,确认没有旧回调或快照残留。对于低概率问题,还需要固定触发方式多轮复测,并记录验证范围,不能把一次成功当成根因已经消除。
易混淆点
快照遮挡、旧 Surface 与 GPU 等待只是候选原因,不是本项目已经确认的根因。
参考资料
内容来源
- Android 技术札记 · 原条目
display-render-freeze