对于很多Android的显示问题,我们需要使用adb shell dumpsys SurfaceFlinger命令来获取SurfaceFlinger的dump信息,这对于我们分析问题有很大的帮助,因此我们这里来详细讲解下SurfaceFlinger的dump.
SurfaceFlinger的dump信息主要通过dumpAllLocked 函数来获取,因此我们这里就以android 5.0在主屏幕上的一份dump来详细说明下dump的作用.
一般dump的第一行都是这样的:
Build configuration: [sf] [libui] [libgui]这说明其实没有打开任何特殊的宏,实际上,如果一下特殊宏打开,第一行log会打印出来:
FRAMEBUFFER_FORCE_FORMAT,HAS_CONTEXT_PRIORITY,NEVER_DEFAULT_TO_ASYNC_MODE,TARGET_DISABLE_TRIPLE_BUFFERING,DONT_USE_FENCE_SYNC一般情况下,这些宏一个都不会打开.
第二行一般是这样的:
Sync configuration: [using: EGL_ANDROID_native_fence_sync EGL_KHR_wait_sync]这行其实打印了目前使用的sync机制,这个值源于这段逻辑:
if (useNativeFenceSync()) { mString.append(" EGL_ANDROID_native_fence_sync"); } if (useFenceSync()) { mString.append(" EGL_KHR_fence_sync"); } if (useWaitSync()) { mString.append(" EGL_KHR_wait_sync"); }注意,一二是互斥的,三可以与一二共存.
第三行是打印的是Vsync相关的参数:
DispSync configuration: app phase 0 ns, sf phase 0 ns, present offset 0 ns (refresh 16666667 ns)这些参数我们还是比较熟悉的,有意思的是打印这些参数时候使用的语法:
result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, " "present offset %d ns (refresh %" PRId64 " ns)", vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, PRESENT_TIME_OFFSET_FROM_VSYNC_NS, mHwc->getRefreshPeriod(HWC_DISPLAY_PRIMARY));PRId64的用法很独特,这是一种跨平台的打印64位整数的做法:
printf("%" PRId64 "\n", value); // 相当于64位的: printf("%" "ld" "\n", value); // 或32位的: printf("%" "lld" "\n", value);接下来就是很长的一段layer的dump,一般以这样一句话开始:
Visible layers (count = 9)count的值来源于layersSortedByZ中layer的数量. 接下来就进入各个layer的dump,我们参考代码并以launcher所在的layer为例来解释下各行的意义:
+ Layer 0xb3f92000 (com.sec.android.app.launcher/com.android.launcher2.Launcher) id=870xb3f92000指向当前layer对象的值,括号中是当前layer的名称,id是创建layer时产生的序列号.
接下来的两段是两个Region的dump,每个region可能包含多个区域,所以这里count也可能不等于1. 前两行的值来源于activeTransparentRegion,表示的是这个layer里面透明区域的大小. 后两行值来源于visibleRegion,表示可见区域的大小.
上面这段dump源自这段代码:
result.appendFormat( " " "layerStack=M, z=