SufraceFlinger图像合成原理(6)-SurfaceFlinger 常用debug 方式

114 阅读3分钟

比较常用的SurfaceFlinger 的debug 方式包括下面三种:winscope、dump、sys trace。

winscope:适用用闪黑闪屏动态异常

dump:适用于静态显示异常

sys trace:适用于分析绘制流程或卡顿问题

6.1 winscope

适用于逐帧查看Layer 信息或窗口状态:

官网连接:

source.android.google.cn/docs/core/g…

抓取

  1. 记录 SurfaceFlinger Layer的跟踪:
adb shell su root service call SurfaceFlinger 1025 i32 1
adb shell su root service call SurfaceFlinger 1025 i32 0

取出trace文件

adb pull /data/misc/wmtrace/layers_trace.pb layers_trace.pb

2. 记录 WindowManager 的跟踪情况:

adb shell cmd window tracing start
adb shell cmd window tracing stop

取出trace文件

adb pull /data/misc/wmtrace/wm_trace.pb wm_trace.pb

或者直接将文件夹pull 出来

adb pull /data/misc/wmtrace

分析

工具在源码路径如下:

android/prebuilts/misc/common/winscope

打开winscope.html,选择pb 文件,下面以layers_trace.pb为例:

6.2 dump

抓取

adb shell dumpsys SurfaceFlinger >sf.txt

当前hwc 合成layer, 顺序为从上到下:

Display 1 HWC layers:
-----------------------------------------------------------------------------------------------------------------------------------------------
 Layer name
           Z |  Window Type |  Comp Type |  Transform |   Disp Frame (LTRB) |          Source Crop (LTRB) |     Frame Rate (Explicit) [Focused]
-----------------------------------------------------------------------------------------------------------------------------------------------
 SurfaceView - com.baidu.naviauto/com.baidu.naviauto.NaviAutoActivity#0
  rel     -2 |            0 |     CLIENT |          0 |    0    0 1440 1920 |    0.0    0.0 1440.0 1920.0 |                              [*]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 com.baidu.naviauto/com.baidu.naviauto.NaviAutoActivity#0
  rel      0 |            1 |     CLIENT |          0 |    0    0 1440 1920 |    0.0    0.0 1440.0 1920.0 |                              [*]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 StatusBar#0
  rel      0 |         2000 |     CLIENT |          0 |    0    0 1440   96 |    0.0    0.0 1440.0   96.0 |                              [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Background for -SurfaceView - dock#0
  rel     -1 |            0 |     CLIENT |          0 |   98 1796 1342 1912 |    0.0    0.0    0.0    0.0 |                              [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 dock#0
  rel      0 |         2059 |     CLIENT |          0 |    0 1796 1440 1920 |    0.0    0.0 1440.0  124.0 |                              [ ]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

分析

所有layer 信息,

常用的包括:

  • layerStack:可以理解为上层的display id
  • z:zOrder ,越大越靠上,最小-2
  • pos:位置
  • Size:大小
  • crop:被裁减大小,会影响layer 大小
  • parent:父layer
+ BufferQueueLayer (com.baidu.naviauto/com.baidu.naviauto.NaviAutoActivity#0)
  Region TransparentRegion (this=0 count=0)
  Region VisibleRegion (this=0 count=1)
    [  0,   0, 1440, 1920]
  Region SurfaceDamageRegion (this=0 count=0)
      layerStack=   0, z=        0, pos=(0,0), size=(1440,1920), crop=[  0,   0, 1440, 1920], cornerRadius=0.000000, isProtected=0, isOpaque=0, invalidate=0, dataspace=Default, defaultPixelFormat=RGBA_8888, backgroundBlurRadius=0, color=(0.000,0.000,0.000,1.000), flags=0x00000000, tr=[0.00, 0.00][0.00, 0.00]
      parent=c024748 com.baidu.naviauto/com.baidu.naviauto.NaviAutoActivity#0
      zOrderRelativeOf=none
      activeBuffer=[1440x1920:1472,RGBA_8888], tr=[0.00, 0.00][0.00, 0.00] queued-frames=0, mRefreshPending=0, metadata={windowType:1, ownerUID:10080}, cornerRadiusCrop=[0.00, 0.00, 0.00, 0.00],  shadowRadius=0.000, 
  flyme extension:

6.3 systrace

抓取

adb shell perfetto -o /data/misc/perfetto-traces/trace_file.perfetto-trace -t 10s sched freq idle am wm gfx view

取出文件:

adb pull /data/misc/perfetto-traces/trace_file.perfetto-trace .

打开以下连接开始分析trace:

ui.perfetto.dev/

分析

  1. 应用进程:

主线程比较简单,主要是绘制三部曲,这里重点看下渲染线程:

每次硬件加速绘制都会调用Surface.unlockCanvasAndPost,一直到绘制完成queueBuffer 流程如下,标红色背景为sys trace 中会打印的方法:

Surface.unlockCanvasAndPost()

-> HwuiContext::unlockAndPost()

->HardwareRenderer::syncAndDraw()

->RenderProxy.cpp ::syncAndDrawFrame()

-> DrawFrameTask::drawFrame()

-> DrawFrameTask::run() 渲染线程开始执行绘制操作

-> DrawFrameTask::syncFrameState 与主线程同步数据,这个阶段在用AutoMutex加锁,主线程等待

->CanvasContext::prepareTree

-> CanvasContext::draw 通过调用OpenGLPipeline方法开始绘制

->SkSurface::flushAndSubmit() 提交绘制请求到GPU

->SkiaOpenGLPipeline::swapBuffers (CanvasContext::draw()中调用)交换buffer 到SurfaceFlinger

->eglSwapBuffersWithDamageKHR()该方法执行完成后,将回调ANativeWindow::queueBuffer进一步回调到

->Surface::hook_queueBuffer() 到现在应用进程绘制完成

  1. SurfaceFlinger:

  • onMessageInvalidate

    •   遍历所有layer,通过acquireBuffer 获取buffer 更新
  • onMessageRefresh

    • 计算可见layer,计算脏区,保存在类Output::mCurrentOutputLayersOrderedByZ中
    • prepareFrame 和Hwbinder 通信选择合成策略,需要显示的数据已经送到HWC,且每一层Layer的合成方式已经确定,Buffer也只是将Buffer的handle传给底层的HWC,并没有传Buffer里面的内容,这里创建底层HWCLayer
    • finishFrame finishFrame 主要处理需要GPU合成的layer,将Client端的Layer渲染到FBTarget(GPU 作为client dequeueBuffer进行渲染,然后通过queueBuffer到BufferQueue,再acquireBuffer ,将各layer 合成后的数据保存在FBTarget,通过setClientTarget给HWC设置Client端的合成结果,传给底层进行显示)
    • postFramebuffer 告诉HWC开始做最后的合成了,包括client和device合成
    • postComposition 到此一次合成处理完成,REFRESH处理完成。下一个Vsync到来时,新的一次合成