【Android】SurfaceFlinger Dumpsys信息分析
SurfaceFlinger Dumpsys信息分析
dumpsys Surfaceflinger 用来输出SurfaceFlinger服务的状态信息,利用这些信息可以分析Android 画面层次、Display配置等等信息。
- 本文基于Android14。
dumpsys的实现
dumpsys Surfaceflinger命令对应的源码实现如下
- 源文件:frameworks/native/cmds/dumpsys/dumpsys.cpp
- 函数:status_t Dumpsys::startDumpThread
status_t Dumpsys::startDumpThread(int dumpTypeFlags, const String16& serviceName,const Vector<String16>& args) {sp<IBinder> service = sm_->checkService(serviceName);if (service == nullptr) {std::cerr << "Can't find service: " << serviceName << std::endl;return NAME_NOT_FOUND;}int sfd[2];if (pipe(sfd) != 0) {std::cerr << "Failed to create pipe to dump service info for " << serviceName << ": "<< strerror(errno) << std::endl;return -errno;}redirectFd_ = unique_fd(sfd[0]);unique_fd remote_end(sfd[1]);sfd[0] = sfd[1] = -1;// dump blocks until completion, so spawn a thread..activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {if (dumpTypeFlags & TYPE_PID) {status_t err = dumpPidToFd(service, remote_end, dumpTypeFlags == TYPE_PID);reportDumpError(serviceName, err, "dumping PID");}if (dumpTypeFlags & TYPE_STABILITY) {status_t err = dumpStabilityToFd(service, remote_end);reportDumpError(serviceName, err, "dumping stability");}if (dumpTypeFlags & TYPE_THREAD) {status_t err = dumpThreadsToFd(service, remote_end);reportDumpError(serviceName, err, "dumping thread info");}if (dumpTypeFlags & TYPE_CLIENTS) {status_t err = dumpClientsToFd(service, remote_end);reportDumpError(serviceName, err, "dumping clients info");}// other types always act as a header, this is usually longerif (dumpTypeFlags & TYPE_DUMP) {// 走这里!!!!!status_t err = service->dump(remote_end.get(), args);reportDumpError(serviceName, err, "dumping");}});return OK;
}
其实,就是调用对应Service的dump函数。经过IPC,调用到SurfaceFlinger的doDump接口。
- 源文件:frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
- 函数:void SurfaceFlinger::setPowerMode
这个函数中,SurfaceFlinger将服务的相关信息dump出来。
status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {std::string result;IPCThreadState* ipc = IPCThreadState::self();const int pid = ipc->getCallingPid();const int uid = ipc->getCallingUid();if ((uid != AID_SHELL) &&!PermissionCache::checkPermission(sDump, pid, uid)) {StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n",pid, uid);} else {static const std::unordered_map<std::string, Dumper> dumpers = {{"--comp-displays"s, dumper(&SurfaceFlinger::dumpCompositionDisplays)},{"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},{"--displays"s, dumper(&SurfaceFlinger::dumpDisplays)},{"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)},{"--events"s, dumper(&SurfaceFlinger::dumpEvents)},{"--frametimeline"s, argsDumper(&SurfaceFlinger::dumpFrameTimeline)},{"--hwclayers"s, dumper(&SurfaceFlinger::dumpHwcLayersMinidumpLocked)},{"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)},{"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)},{"--list"s, dumper(&SurfaceFlinger::listLayersLocked)},{"--planner"s, argsDumper(&SurfaceFlinger::dumpPlannerInfo)},{"--scheduler"s, dumper(&SurfaceFlinger::dumpScheduler)},{"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)},{"--vsync"s, dumper(&SurfaceFlinger::dumpVsync)},{"--wide-color"s, dumper(&SurfaceFlinger::dumpWideColorInfo)},};const auto flag = args.empty() ? ""s : std::string(String8(args[0]));// Traversal of drawing state must happen on the main thread.// Otherwise, SortedVector may have shared ownership during concurrent// traversals, which can result in use-after-frees.std::string compositionLayers;mScheduler->schedule([&] {StringAppendF(&compositionLayers, "Composition layers\n");mDrawingState.traverseInZOrder([&](Layer* layer) {auto* compositionState = layer->getCompositionState();if (!compositionState || !compositionState->isVisible) return;android::base::StringAppendF(&compositionLayers, "* Layer %p (%s)\n", layer,layer->getDebugName() ? layer->getDebugName(): "<unknown>");compositionState->dump(compositionLayers);});}).get();bool dumpLayers = true;{TimedLock lock(mStateLock, s2ns(1), __func__);if (!lock.locked()) {StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n",strerror(-lock.status), lock.status);}if (const auto it = dumpers.find(flag); it != dumpers.end()) {(it->second)(args, asProto, result);dumpLayers = false;} else if (!asProto) {dumpAllLocked(args, compositionLayers, result);}}if (dumpLayers) {LayersTraceFileProto traceFileProto = mLayerTracing.createTraceFileProto();LayersTraceProto* layersTrace = traceFileProto.add_entry();LayersProto layersProto = dumpProtoFromMainThread();layersTrace->mutable_layers()->Swap(&layersProto);auto displayProtos = dumpDisplayProto();layersTrace->mutable_displays()->Swap(&displayProtos);if (asProto) {result.append(traceFileProto.SerializeAsString());} else {// Dump info that we need to access from the main threadconst auto layerTree = LayerProtoParser::generateLayerTree(layersTrace->layers());result.append(LayerProtoParser::layerTreeToString(layerTree));result.append("\n");dumpOffscreenLayers(result);}}}write(fd, result.c_str(), result.size());return NO_ERROR;
}
SurfaceFlinger Dump部分信息分析
SurfaceFlinger编译配置
Build configuration:
[sf PRESENT_TIME_OFFSET=0
FORCE_HWC_FOR_RBG_TO_YUV=1
MAX_VIRT_DISPLAY_DIM=4096
RUNNING_WITHOUT_SYNC_FRAMEWORK=0
NUM_FRAMEBUFFER_SURFACE_BUFFERS=3]
sf:表示SurfacFlinger
PRESENT_TIME_OFFSET:垂直同步偏移,用来兼容垂直同步信号误差的(主要指跨进程的通知耗时),nanoseconds级别。
FORCE_HWC_FOR_RBG_TO_YUV:使用HWC进行 RGB到YUV的转换。
MAX_VIRT_DISPLAY_DIM:虚拟Display的最大尺寸,创建虚拟Display时,其宽或高要在这个范围内超过的话会创建失败。
RUNNING_WITHOUT_SYNC_FRAMEWORK: Sync同步框架是否开启,默认是开启的。
NUM_FRAMEBUFFER_SURFACE_BUFFERS:SurfaceFlinger中BufferQueue,一次申请Buffer时可以申请的最大数量(NUM_FRAMEBUFFER_SURFACE_BUFFERS减去1)。如果是3,减去1就是2.就是双Buffer机制。默认最高支持63个。一般都使用2,如果出现Jank情况下,可以适当调大(但是会更耗时系统资源)
显示器信息
Display identification data:
Display 100 (HWC display 0): invalid EDID
此处表示显示器信息(硬件信息)。EDID全称Extended Display Identification Data,存储在显示器寄存器中的一组有关于显示器属性值的信息。比如显示器名称、端口号之类。如果显示器没有提供这些信息,解析时就是显示ivalid EDID(PS此处显示的HWC,也就是PhysicalDisplay)
Wide-Color information:
Device supports wide color: 1
Device uses color management: 1
DisplayColorSetting: Managed
Display 100 color modes:ColorMode::NATIVE (0)Current color mode: ColorMode::NATIVE (0)
此处是显示器的色域信息,支持广色域、支持色彩管理、设置管理功能已经开启、支持1中颜色模式(Native)。
广色域是一种色彩背光技术,其色彩覆盖率能达到NSTC(National Television System Committe)标准的92%及以上。比如量子点LED背光能达到110%(比如AOC的量子点显示器大概在3499元)。使用广色域,可以让显示器的显示效果更佳鲜艳,但并不是NSTC覆盖标准越高越高,超过人眼的可识别范围的色彩是人类是无法分辨的(人眼识别范围(380~780nm)的光波波长。
Sync configuration: [using: EGL_ANDROID_native_fence_sync EGL_KHR_wait_sync]
这条信息表示,支持OpenGLES同步(Sync)。OpenGLES Sync依赖于两个扩EGL_ANDROID_native_fence_sync、EGL_KHR_wait_sync
Layer信息
Visible layers (count = 200)
Composition layers
当前显示的图层数目是200个
Display状态
Displays (1 entries)
有1个Display
Display 100
(Display ID是 100)
connectionType=Internal
(内置类型)
ColorMode::NATIVE
(颜色模式为Native)
deviceProductInfo=nullopt
(产品信息为空)
name="Primary display"
默认的Display
powerMode=Off
(电源状态是OFF)
activeMode=60.00 Hz (60.00 Hz)
(刷新率是60帧)
- 如果通过scrpy投屏可以看到对应的Virtual Display
Virtual Display 12529715046768705014name="scrcpy"powerMode=On
其他信息省略。