Loading services/surfaceflinger/SurfaceFlinger.cpp +134 −161 Original line number Original line Diff line number Diff line Loading @@ -5952,20 +5952,22 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { !PermissionCache::checkPermission(sDump, pid, uid)) { !PermissionCache::checkPermission(sDump, pid, uid)) { StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n", StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid); pid, uid); } else { write(fd, result.c_str(), result.size()); Dumper hwclayersDump = [this](const DumpArgs&, bool, std::string& result) return NO_ERROR; FTL_FAKE_GUARD(mStateLock) -> void const { } if (mLayerLifecycleManagerEnabled) { mScheduler if (asProto && args.empty()) { ->schedule([this, &result]() FTL_FAKE_GUARD(kMainThreadContext) perfetto::protos::LayersTraceFileProto traceFileProto = FTL_FAKE_GUARD(mStateLock) { mLayerTracing.createTraceFileProto(); dumpHwcLayersMinidump(result); perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry(); }) perfetto::protos::LayersProto layersProto = dumpProtoFromMainThread(); .get(); layersTrace->mutable_layers()->Swap(&layersProto); } else { auto displayProtos = dumpDisplayProto(); dumpHwcLayersMinidumpLockedLegacy(result); layersTrace->mutable_displays()->Swap(&displayProtos); result.append(traceFileProto.SerializeAsString()); write(fd, result.c_str(), result.size()); return NO_ERROR; } } }; static const std::unordered_map<std::string, Dumper> dumpers = { static const std::unordered_map<std::string, Dumper> dumpers = { {"--comp-displays"s, dumper(&SurfaceFlinger::dumpCompositionDisplays)}, {"--comp-displays"s, dumper(&SurfaceFlinger::dumpCompositionDisplays)}, Loading @@ -5974,8 +5976,9 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)}, {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)}, {"--events"s, dumper(&SurfaceFlinger::dumpEvents)}, {"--events"s, dumper(&SurfaceFlinger::dumpEvents)}, {"--frametimeline"s, argsDumper(&SurfaceFlinger::dumpFrameTimeline)}, {"--frametimeline"s, argsDumper(&SurfaceFlinger::dumpFrameTimeline)}, {"--frontend"s, mainThreadDumper(&SurfaceFlinger::dumpFrontEnd)}, {"--hdrinfo"s, dumper(&SurfaceFlinger::dumpHdrInfo)}, {"--hdrinfo"s, dumper(&SurfaceFlinger::dumpHdrInfo)}, {"--hwclayers"s, std::move(hwclayersDump)}, {"--hwclayers"s, mainThreadDumper(&SurfaceFlinger::dumpHwcLayersMinidump)}, {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)}, {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)}, {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)}, {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)}, {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)}, {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)}, Loading @@ -5984,10 +5987,14 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { {"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)}, {"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)}, {"--vsync"s, dumper(&SurfaceFlinger::dumpVsync)}, {"--vsync"s, dumper(&SurfaceFlinger::dumpVsync)}, {"--wide-color"s, dumper(&SurfaceFlinger::dumpWideColorInfo)}, {"--wide-color"s, dumper(&SurfaceFlinger::dumpWideColorInfo)}, {"--frontend"s, dumper(&SurfaceFlinger::dumpFrontEnd)}, }; }; const auto flag = args.empty() ? ""s : std::string(String8(args[0])); const auto flag = args.empty() ? ""s : std::string(String8(args[0])); if (const auto it = dumpers.find(flag); it != dumpers.end()) { (it->second)(args, asProto, result); write(fd, result.c_str(), result.size()); return NO_ERROR; } // Traversal of drawing state must happen on the main thread. // Traversal of drawing state must happen on the main thread. // Otherwise, SortedVector may have shared ownership during concurrent // Otherwise, SortedVector may have shared ownership during concurrent Loading @@ -5995,97 +6002,10 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { std::string compositionLayers; std::string compositionLayers; mScheduler mScheduler ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { if (!mLayerLifecycleManagerEnabled) { dumpVisibleFrontEnd(compositionLayers); 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); }); } else { std::ostringstream out; out << "\nComposition list\n"; ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachVisibleSnapshot( [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) { if (snapshot->hasSomethingToDraw()) { if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } out << " " << *snapshot << "\n"; } }); out << "\nInput list\n"; lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachInputSnapshot( [&](const frontend::LayerSnapshot& snapshot) { if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } out << " " << snapshot << "\n"; }); out << "\nLayer Hierarchy\n" << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n" << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n"; compositionLayers = out.str(); dumpHwcLayersMinidump(compositionLayers); } }) }) .get(); .get(); dumpAll(args, compositionLayers, result); 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) { perfetto::protos::LayersTraceFileProto traceFileProto = mLayerTracing.createTraceFileProto(); perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry(); perfetto::protos::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 thread const auto layerTree = LayerProtoParser::generateLayerTree(layersTrace->layers()); result.append(LayerProtoParser::layerTreeToString(layerTree)); result.append("\n"); dumpOffscreenLayers(result); } } } write(fd, result.c_str(), result.size()); write(fd, result.c_str(), result.size()); return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -6297,8 +6217,6 @@ void SurfaceFlinger::dumpHdrInfo(std::string& result) const { } } void SurfaceFlinger::dumpFrontEnd(std::string& result) { void SurfaceFlinger::dumpFrontEnd(std::string& result) { mScheduler ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { std::ostringstream out; std::ostringstream out; out << "\nComposition list\n"; out << "\nComposition list\n"; ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; Loading @@ -6312,8 +6230,7 @@ void SurfaceFlinger::dumpFrontEnd(std::string& result) { out << "\nInput list\n"; out << "\nInput list\n"; lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachInputSnapshot( mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) { [&](const frontend::LayerSnapshot& snapshot) { if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; Loading @@ -6322,12 +6239,59 @@ void SurfaceFlinger::dumpFrontEnd(std::string& result) { }); }); out << "\nLayer Hierarchy\n" out << "\nLayer Hierarchy\n" << mLayerHierarchyBuilder.getHierarchy().dump() << mLayerHierarchyBuilder.getHierarchy().dump() << "\nOffscreen Hierarchy\n" << "\nOffscreen Hierarchy\n" << mLayerHierarchyBuilder.getOffscreenHierarchy().dump() << "\n\n"; << mLayerHierarchyBuilder.getOffscreenHierarchy().dump() << "\n\n"; result.append(out.str()); result.append(out.str()); }) } .get(); void SurfaceFlinger::dumpVisibleFrontEnd(std::string& result) { if (!mLayerLifecycleManagerEnabled) { StringAppendF(&result, "Composition layers\n"); mDrawingState.traverseInZOrder([&](Layer* layer) { auto* compositionState = layer->getCompositionState(); if (!compositionState || !compositionState->isVisible) return; android::base::StringAppendF(&result, "* Layer %p (%s)\n", layer, layer->getDebugName() ? layer->getDebugName() : "<unknown>"); compositionState->dump(result); }); StringAppendF(&result, "Offscreen Layers\n"); for (Layer* offscreenLayer : mOffscreenLayers) { offscreenLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) { layer->dumpOffscreenDebugInfo(result); }); } } else { std::ostringstream out; out << "\nComposition list\n"; ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachVisibleSnapshot( [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) { if (snapshot->hasSomethingToDraw()) { if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } out << " " << *snapshot << "\n"; } }); out << "\nInput list\n"; lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) { if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } out << " " << snapshot << "\n"; }); out << "\nLayer Hierarchy\n" << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n" << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n"; result = out.str(); dumpHwcLayersMinidump(result); } } } perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { Loading Loading @@ -6428,7 +6392,7 @@ void SurfaceFlinger::dumpOffscreenLayers(std::string& result) { } } void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const { void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const { for (const auto& [token, display] : mDisplays) { for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { const auto displayId = HalDisplayId::tryCast(display->getId()); const auto displayId = HalDisplayId::tryCast(display->getId()); if (!displayId) { if (!displayId) { continue; continue; Loading @@ -6445,7 +6409,10 @@ void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) cons } } void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { for (const auto& [token, display] : mDisplays) { if (!mLayerLifecycleManagerEnabled) { return dumpHwcLayersMinidumpLockedLegacy(result); } for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { const auto displayId = HalDisplayId::tryCast(display->getId()); const auto displayId = HalDisplayId::tryCast(display->getId()); if (!displayId) { if (!displayId) { continue; continue; Loading @@ -6470,8 +6437,14 @@ void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { } } } } void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers, void SurfaceFlinger::dumpAll(const DumpArgs& args, const std::string& compositionLayers, std::string& result) const { std::string& result) const { TimedLock lock(mStateLock, s2ns(1), __func__); if (!lock.locked()) { StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n", strerror(-lock.status), lock.status); } const bool colorize = !args.empty() && args[0] == String16("--color"); const bool colorize = !args.empty() && args[0] == String16("--color"); Colorizer colorizer(colorize); Colorizer colorizer(colorize); Loading services/surfaceflinger/SurfaceFlinger.h +34 −6 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,8 @@ * NOTE: Make sure this file doesn't include anything from <gl/ > or <gl2/ > * NOTE: Make sure this file doesn't include anything from <gl/ > or <gl2/ > */ */ #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/thread_annotations.h> #include <android-base/thread_annotations.h> #include <android/gui/BnSurfaceComposer.h> #include <android/gui/BnSurfaceComposer.h> #include <android/gui/DisplayStatInfo.h> #include <android/gui/DisplayStatInfo.h> Loading Loading @@ -77,6 +79,7 @@ #include "FrontEnd/LayerSnapshotBuilder.h" #include "FrontEnd/LayerSnapshotBuilder.h" #include "FrontEnd/TransactionHandler.h" #include "FrontEnd/TransactionHandler.h" #include "LayerVector.h" #include "LayerVector.h" #include "MutexUtils.h" #include "Scheduler/ISchedulerCallback.h" #include "Scheduler/ISchedulerCallback.h" #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/RefreshRateStats.h" #include "Scheduler/RefreshRateStats.h" Loading Loading @@ -478,22 +481,46 @@ private: return std::bind(std::forward<F>(dump), _3); return std::bind(std::forward<F>(dump), _3); } } Dumper lockedDumper(Dumper dump) { return [this, dump](const DumpArgs& args, bool asProto, std::string& result) -> void { TimedLock lock(mStateLock, s2ns(1), __func__); if (!lock.locked()) { base::StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n", strerror(-lock.status), lock.status); } dump(args, asProto, result); }; } template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr> template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr> Dumper dumper(F dump) { Dumper dumper(F dump) { using namespace std::placeholders; using namespace std::placeholders; return std::bind(dump, this, _3); return lockedDumper(std::bind(dump, this, _3)); } } template <typename F> template <typename F> Dumper argsDumper(F dump) { Dumper argsDumper(F dump) { using namespace std::placeholders; using namespace std::placeholders; return std::bind(dump, this, _1, _3); return lockedDumper(std::bind(dump, this, _1, _3)); } } template <typename F> template <typename F> Dumper protoDumper(F dump) { Dumper protoDumper(F dump) { using namespace std::placeholders; using namespace std::placeholders; return std::bind(dump, this, _1, _2, _3); return lockedDumper(std::bind(dump, this, _1, _2, _3)); } template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr> Dumper mainThreadDumper(F dump) { using namespace std::placeholders; Dumper dumper = std::bind(dump, this, _3); return [this, dumper](const DumpArgs& args, bool asProto, std::string& result) -> void { mScheduler ->schedule( [&args, asProto, &result, dumper]() FTL_FAKE_GUARD(kMainThreadContext) FTL_FAKE_GUARD(mStateLock) { dumper(args, asProto, result); }) .get(); }; } } // Maximum allowed number of display frames that can be set through backdoor // Maximum allowed number of display frames that can be set through backdoor Loading Loading @@ -1080,8 +1107,8 @@ private: /* /* * Debugging & dumpsys * Debugging & dumpsys */ */ void dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers, void dumpAll(const DumpArgs& args, const std::string& compositionLayers, std::string& result) const REQUIRES(mStateLock); std::string& result) const EXCLUDES(mStateLock); void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext); void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext); void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock); void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock); Loading @@ -1103,7 +1130,8 @@ private: void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock); void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock); void dumpFrontEnd(std::string& result); void dumpFrontEnd(std::string& result) REQUIRES(kMainThreadContext); void dumpVisibleFrontEnd(std::string& result) REQUIRES(mStateLock, kMainThreadContext); perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +134 −161 Original line number Original line Diff line number Diff line Loading @@ -5952,20 +5952,22 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { !PermissionCache::checkPermission(sDump, pid, uid)) { !PermissionCache::checkPermission(sDump, pid, uid)) { StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n", StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid); pid, uid); } else { write(fd, result.c_str(), result.size()); Dumper hwclayersDump = [this](const DumpArgs&, bool, std::string& result) return NO_ERROR; FTL_FAKE_GUARD(mStateLock) -> void const { } if (mLayerLifecycleManagerEnabled) { mScheduler if (asProto && args.empty()) { ->schedule([this, &result]() FTL_FAKE_GUARD(kMainThreadContext) perfetto::protos::LayersTraceFileProto traceFileProto = FTL_FAKE_GUARD(mStateLock) { mLayerTracing.createTraceFileProto(); dumpHwcLayersMinidump(result); perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry(); }) perfetto::protos::LayersProto layersProto = dumpProtoFromMainThread(); .get(); layersTrace->mutable_layers()->Swap(&layersProto); } else { auto displayProtos = dumpDisplayProto(); dumpHwcLayersMinidumpLockedLegacy(result); layersTrace->mutable_displays()->Swap(&displayProtos); result.append(traceFileProto.SerializeAsString()); write(fd, result.c_str(), result.size()); return NO_ERROR; } } }; static const std::unordered_map<std::string, Dumper> dumpers = { static const std::unordered_map<std::string, Dumper> dumpers = { {"--comp-displays"s, dumper(&SurfaceFlinger::dumpCompositionDisplays)}, {"--comp-displays"s, dumper(&SurfaceFlinger::dumpCompositionDisplays)}, Loading @@ -5974,8 +5976,9 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)}, {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)}, {"--events"s, dumper(&SurfaceFlinger::dumpEvents)}, {"--events"s, dumper(&SurfaceFlinger::dumpEvents)}, {"--frametimeline"s, argsDumper(&SurfaceFlinger::dumpFrameTimeline)}, {"--frametimeline"s, argsDumper(&SurfaceFlinger::dumpFrameTimeline)}, {"--frontend"s, mainThreadDumper(&SurfaceFlinger::dumpFrontEnd)}, {"--hdrinfo"s, dumper(&SurfaceFlinger::dumpHdrInfo)}, {"--hdrinfo"s, dumper(&SurfaceFlinger::dumpHdrInfo)}, {"--hwclayers"s, std::move(hwclayersDump)}, {"--hwclayers"s, mainThreadDumper(&SurfaceFlinger::dumpHwcLayersMinidump)}, {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)}, {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)}, {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)}, {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)}, {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)}, {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)}, Loading @@ -5984,10 +5987,14 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { {"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)}, {"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)}, {"--vsync"s, dumper(&SurfaceFlinger::dumpVsync)}, {"--vsync"s, dumper(&SurfaceFlinger::dumpVsync)}, {"--wide-color"s, dumper(&SurfaceFlinger::dumpWideColorInfo)}, {"--wide-color"s, dumper(&SurfaceFlinger::dumpWideColorInfo)}, {"--frontend"s, dumper(&SurfaceFlinger::dumpFrontEnd)}, }; }; const auto flag = args.empty() ? ""s : std::string(String8(args[0])); const auto flag = args.empty() ? ""s : std::string(String8(args[0])); if (const auto it = dumpers.find(flag); it != dumpers.end()) { (it->second)(args, asProto, result); write(fd, result.c_str(), result.size()); return NO_ERROR; } // Traversal of drawing state must happen on the main thread. // Traversal of drawing state must happen on the main thread. // Otherwise, SortedVector may have shared ownership during concurrent // Otherwise, SortedVector may have shared ownership during concurrent Loading @@ -5995,97 +6002,10 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { std::string compositionLayers; std::string compositionLayers; mScheduler mScheduler ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { if (!mLayerLifecycleManagerEnabled) { dumpVisibleFrontEnd(compositionLayers); 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); }); } else { std::ostringstream out; out << "\nComposition list\n"; ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachVisibleSnapshot( [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) { if (snapshot->hasSomethingToDraw()) { if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } out << " " << *snapshot << "\n"; } }); out << "\nInput list\n"; lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachInputSnapshot( [&](const frontend::LayerSnapshot& snapshot) { if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } out << " " << snapshot << "\n"; }); out << "\nLayer Hierarchy\n" << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n" << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n"; compositionLayers = out.str(); dumpHwcLayersMinidump(compositionLayers); } }) }) .get(); .get(); dumpAll(args, compositionLayers, result); 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) { perfetto::protos::LayersTraceFileProto traceFileProto = mLayerTracing.createTraceFileProto(); perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry(); perfetto::protos::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 thread const auto layerTree = LayerProtoParser::generateLayerTree(layersTrace->layers()); result.append(LayerProtoParser::layerTreeToString(layerTree)); result.append("\n"); dumpOffscreenLayers(result); } } } write(fd, result.c_str(), result.size()); write(fd, result.c_str(), result.size()); return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -6297,8 +6217,6 @@ void SurfaceFlinger::dumpHdrInfo(std::string& result) const { } } void SurfaceFlinger::dumpFrontEnd(std::string& result) { void SurfaceFlinger::dumpFrontEnd(std::string& result) { mScheduler ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { std::ostringstream out; std::ostringstream out; out << "\nComposition list\n"; out << "\nComposition list\n"; ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; Loading @@ -6312,8 +6230,7 @@ void SurfaceFlinger::dumpFrontEnd(std::string& result) { out << "\nInput list\n"; out << "\nInput list\n"; lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachInputSnapshot( mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) { [&](const frontend::LayerSnapshot& snapshot) { if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; Loading @@ -6322,12 +6239,59 @@ void SurfaceFlinger::dumpFrontEnd(std::string& result) { }); }); out << "\nLayer Hierarchy\n" out << "\nLayer Hierarchy\n" << mLayerHierarchyBuilder.getHierarchy().dump() << mLayerHierarchyBuilder.getHierarchy().dump() << "\nOffscreen Hierarchy\n" << "\nOffscreen Hierarchy\n" << mLayerHierarchyBuilder.getOffscreenHierarchy().dump() << "\n\n"; << mLayerHierarchyBuilder.getOffscreenHierarchy().dump() << "\n\n"; result.append(out.str()); result.append(out.str()); }) } .get(); void SurfaceFlinger::dumpVisibleFrontEnd(std::string& result) { if (!mLayerLifecycleManagerEnabled) { StringAppendF(&result, "Composition layers\n"); mDrawingState.traverseInZOrder([&](Layer* layer) { auto* compositionState = layer->getCompositionState(); if (!compositionState || !compositionState->isVisible) return; android::base::StringAppendF(&result, "* Layer %p (%s)\n", layer, layer->getDebugName() ? layer->getDebugName() : "<unknown>"); compositionState->dump(result); }); StringAppendF(&result, "Offscreen Layers\n"); for (Layer* offscreenLayer : mOffscreenLayers) { offscreenLayer->traverse(LayerVector::StateSet::Drawing, [&](Layer* layer) { layer->dumpOffscreenDebugInfo(result); }); } } else { std::ostringstream out; out << "\nComposition list\n"; ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachVisibleSnapshot( [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) { if (snapshot->hasSomethingToDraw()) { if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } out << " " << *snapshot << "\n"; } }); out << "\nInput list\n"; lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) { if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; } out << " " << snapshot << "\n"; }); out << "\nLayer Hierarchy\n" << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n" << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n"; result = out.str(); dumpHwcLayersMinidump(result); } } } perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { Loading Loading @@ -6428,7 +6392,7 @@ void SurfaceFlinger::dumpOffscreenLayers(std::string& result) { } } void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const { void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const { for (const auto& [token, display] : mDisplays) { for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { const auto displayId = HalDisplayId::tryCast(display->getId()); const auto displayId = HalDisplayId::tryCast(display->getId()); if (!displayId) { if (!displayId) { continue; continue; Loading @@ -6445,7 +6409,10 @@ void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) cons } } void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { for (const auto& [token, display] : mDisplays) { if (!mLayerLifecycleManagerEnabled) { return dumpHwcLayersMinidumpLockedLegacy(result); } for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { const auto displayId = HalDisplayId::tryCast(display->getId()); const auto displayId = HalDisplayId::tryCast(display->getId()); if (!displayId) { if (!displayId) { continue; continue; Loading @@ -6470,8 +6437,14 @@ void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { } } } } void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers, void SurfaceFlinger::dumpAll(const DumpArgs& args, const std::string& compositionLayers, std::string& result) const { std::string& result) const { TimedLock lock(mStateLock, s2ns(1), __func__); if (!lock.locked()) { StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n", strerror(-lock.status), lock.status); } const bool colorize = !args.empty() && args[0] == String16("--color"); const bool colorize = !args.empty() && args[0] == String16("--color"); Colorizer colorizer(colorize); Colorizer colorizer(colorize); Loading
services/surfaceflinger/SurfaceFlinger.h +34 −6 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,8 @@ * NOTE: Make sure this file doesn't include anything from <gl/ > or <gl2/ > * NOTE: Make sure this file doesn't include anything from <gl/ > or <gl2/ > */ */ #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/thread_annotations.h> #include <android-base/thread_annotations.h> #include <android/gui/BnSurfaceComposer.h> #include <android/gui/BnSurfaceComposer.h> #include <android/gui/DisplayStatInfo.h> #include <android/gui/DisplayStatInfo.h> Loading Loading @@ -77,6 +79,7 @@ #include "FrontEnd/LayerSnapshotBuilder.h" #include "FrontEnd/LayerSnapshotBuilder.h" #include "FrontEnd/TransactionHandler.h" #include "FrontEnd/TransactionHandler.h" #include "LayerVector.h" #include "LayerVector.h" #include "MutexUtils.h" #include "Scheduler/ISchedulerCallback.h" #include "Scheduler/ISchedulerCallback.h" #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/RefreshRateStats.h" #include "Scheduler/RefreshRateStats.h" Loading Loading @@ -478,22 +481,46 @@ private: return std::bind(std::forward<F>(dump), _3); return std::bind(std::forward<F>(dump), _3); } } Dumper lockedDumper(Dumper dump) { return [this, dump](const DumpArgs& args, bool asProto, std::string& result) -> void { TimedLock lock(mStateLock, s2ns(1), __func__); if (!lock.locked()) { base::StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n", strerror(-lock.status), lock.status); } dump(args, asProto, result); }; } template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr> template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr> Dumper dumper(F dump) { Dumper dumper(F dump) { using namespace std::placeholders; using namespace std::placeholders; return std::bind(dump, this, _3); return lockedDumper(std::bind(dump, this, _3)); } } template <typename F> template <typename F> Dumper argsDumper(F dump) { Dumper argsDumper(F dump) { using namespace std::placeholders; using namespace std::placeholders; return std::bind(dump, this, _1, _3); return lockedDumper(std::bind(dump, this, _1, _3)); } } template <typename F> template <typename F> Dumper protoDumper(F dump) { Dumper protoDumper(F dump) { using namespace std::placeholders; using namespace std::placeholders; return std::bind(dump, this, _1, _2, _3); return lockedDumper(std::bind(dump, this, _1, _2, _3)); } template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr> Dumper mainThreadDumper(F dump) { using namespace std::placeholders; Dumper dumper = std::bind(dump, this, _3); return [this, dumper](const DumpArgs& args, bool asProto, std::string& result) -> void { mScheduler ->schedule( [&args, asProto, &result, dumper]() FTL_FAKE_GUARD(kMainThreadContext) FTL_FAKE_GUARD(mStateLock) { dumper(args, asProto, result); }) .get(); }; } } // Maximum allowed number of display frames that can be set through backdoor // Maximum allowed number of display frames that can be set through backdoor Loading Loading @@ -1080,8 +1107,8 @@ private: /* /* * Debugging & dumpsys * Debugging & dumpsys */ */ void dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers, void dumpAll(const DumpArgs& args, const std::string& compositionLayers, std::string& result) const REQUIRES(mStateLock); std::string& result) const EXCLUDES(mStateLock); void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext); void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext); void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock); void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock); Loading @@ -1103,7 +1130,8 @@ private: void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock); void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock); void dumpFrontEnd(std::string& result); void dumpFrontEnd(std::string& result) REQUIRES(kMainThreadContext); void dumpVisibleFrontEnd(std::string& result) REQUIRES(mStateLock, kMainThreadContext); perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, Loading