显示疑难问题分析基础
# Android 显示疑难问题分析基础
# 1. 显示基本流程
分析卡顿需要了解显示的基本流程:
- 绘制过程(DrawFrame)
- 申请 Buffer
- 绘制(HWUI Opengl/Vulkan 视频解码等方式绘制)
- 提交 buffer
- 合成 (Compose):
- 一个 Vsycn 周期内收集到多个 Buffer
- 多个 Buffer 叠合成到一个 Buffer(Device/Clent 合成)
- 送到 panel 显示
- 显示完成,release buffer
整体的 Buffer 流转如下图所示:
# 2 Peffetto 中,显示相关 Slice
# 2.1 Vsync 信号
- VSYNC-app VSYNC-sf,是在 VSYNC—HW 信号基础上重新计算以后发出周期性软件信号
- VSYNC-app 是控制 App 端绘制过程帧率的,VSYNC-sf 是控制 SurfaceFlinger 合成过程的帧率的
- 两者一般会有一定的相位差,用于避免短时间内过高的资源占用。
# 2.2 绘制过程
App 中的帧绘制:
同步 DisplayList 过程会调用到主线程的 wait 操作,会阻塞主线程,绝大部分情况,阻塞时间很短。在 ANR 堆栈中经常会出现类型如下的堆栈信息:
android.graphics.HardwareRenderer.nSyncAndDrawFrame(Native method)
android.graphics.HardwareRenderer.syncAndDrawFrame(HardwareRenderer.java:465)
android.view.ThreadedRenderer.draw(ThreadedRenderer.java:645)
android.view.ViewRootImpl.draw(ViewRootImpl.java:4831)
android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4537)
android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3630)
android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2357)
android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9304)
android.view.Choreographer$CallbackRecord.run(Choreographer.java:1129)
android.view.Choreographer.doCallbacks(Choreographer.java:926)
android.view.Choreographer.doFrame(Choreographer.java:840)
android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1114)
android.os.Handler.handleCallback(Handler.java:938)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loopOnce(Looper.java:210)
android.os.Looper.loop(Looper.java:299)
android.app.ActivityThread.main(ActivityThread.java:8306)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nSyncAndDrawFrame 方法用于发起同步和 RenderThread 后续的回执操作,这里会有一个主线程的 wait 操作,如果这个时候发生了 ANR ,会去扫描所有线程状态,打印出 wait 状态的调用栈信息。如果发生 ANR 的时候,主线程正在执行同步操作,就会看到 nSyncAndDrawFrame 相关堆栈,很多时候并不是同步操作本身造成的。
显示 Buffer 申请与 Fence 处理:
显示 Buffer 的提交:
GPU 渲染过程可能会等待 HWC Fence:
# 2.3 SF 中的合成过程
Vsync 申请与分发过程:
SurfaceFlinger 主线程 commit 过程:
- updateLayerSnapshots 函数负责在每个帧周期中处理图层事务、更新图层状态、生成图层快照,并执行缓冲区闩锁(buffer latching)操作
- chooseRefreshRateForContent 函数用于选择当前的刷新率。
sf 主线程 composite 过程:
- device 合成的情况
OverlayEngine 是 HWC 中处理图层合成的主要线程,调用显示驱动完成显示相关的操作(mtk 平台)。
- client + device 合成的情况
需要注意的是,drawLayers 只是在做 GPU 合成需要的 texture 的准备工作,如果是 drawLayers 本身时间久,则瓶颈是在 CPU, 需分析 CPU 频率, Loading 以及大小核状况
- 在 Client 合成中,“RE Completion” 与 “GPU Completion” 本质上通过同一个 Fence 串联在一起:RenderEngine 提交 GPU 作业并返回一个 Fence ;当该 Fence 发出信号时,表示 GPU 完成了这次 Client 目标缓冲的渲染。
- 这个 Fence 随后充当多重角色:作为 readyFence 入队到 BufferQueue 、作为 client target acquire fence 传递给 HWC 的 setClientTarget 、并被 FrameTracker / TimeStats 记录时序。
Fence 的整体流程分析可以参考下图:
Fence 还有一点需要特别注意,当系统属性配置如下时:
- debug.sf.latch_unsignaled = false
- debug.sf.auto_latch_unsignaled = true
SurfaceFlinger 会被配置为 AutoSingleLayer 模式,会存在锁存 unsignaled buffer 的情况。
AutoSingleLayer 模式主要在视频播放,游戏,相机等场景适用,更多信息可以参考 google 文档:https://source.android.google.cn/docs/core/graphics/unsignaled-buffer-latch?hl=zh-cn
- 01
- Perfetto 上手指南1 —— Trace 的抓取10-08
- 02
- Perfetto 上手指南2 —— 基础使用10-08
- 03
- Perfetto 上手指南3 —— CPU 信息分析10-08