diff options
author | 2024-07-11 23:03:02 +0000 | |
---|---|---|
committer | 2024-07-11 23:03:02 +0000 | |
commit | 516228f07a1078202c915092d4f4acde046053f7 (patch) | |
tree | 8f2936ee07c30a595a6d81eefa51318ff88be8ac | |
parent | da62cb20839940ae274bf1c2307eec7721241a43 (diff) |
Add a workaround to prevent duplicate layers in traces
Track and skip any duplicate layers before adding it to the trace. Capture the transaction trace to disk when we detect this issue to help
identify the root cause.
CL also fixes offscreen layers to capture the layers from the hierarchy.
Flag: EXEMPT bugfix
Bug: 335383156
Test: capture active layers trace
Change-Id: If7158a19b2d090bb35af4c3a143c105b4be3d5bc
-rw-r--r-- | services/surfaceflinger/LayerProtoHelper.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/LayerProtoHelper.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 22 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 3 |
4 files changed, 25 insertions, 7 deletions
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 496033b749..30b8eeefba 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -266,6 +266,7 @@ void LayerProtoHelper::readFromProto(const perfetto::protos::BlurRegion& proto, perfetto::protos::LayersProto LayerProtoFromSnapshotGenerator::generate( const frontend::LayerHierarchy& root) { mLayersProto.clear_layers(); + mVisitedLayers.clear(); std::unordered_set<uint64_t> stackIdsToSkip; if ((mTraceFlags & LayerTracing::TRACE_VIRTUAL_DISPLAYS) == 0) { for (const auto& [layerStack, displayInfo] : mDisplayInfos) { @@ -326,6 +327,10 @@ void LayerProtoFromSnapshotGenerator::writeHierarchyToProto( perfetto::protos::LayerProto* layerProto = mLayersProto.add_layers(); const frontend::RequestedLayerState& layer = *root.getLayer(); frontend::LayerSnapshot* snapshot = getSnapshot(path, layer); + if (mVisitedLayers.find(snapshot->uniqueSequence) != mVisitedLayers.end()) { + TransactionTraceWriter::getInstance().invoke("DuplicateLayer", /* overwrite= */ false); + return; + } LayerProtoHelper::writeSnapshotToProto(layerProto, layer, *snapshot, mTraceFlags); for (const auto& [child, variant] : root.mChildren) { diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 20c226006c..d6720123ac 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -101,6 +101,8 @@ private: const frontend::DisplayInfos& mDisplayInfos; uint32_t mTraceFlags; perfetto::protos::LayersProto mLayersProto; + std::unordered_set<uint32_t> mVisitedLayers; + // winscope expects all the layers, so provide a snapshot even if it not currently drawing std::unordered_map<frontend::LayerHierarchy::TraversalPath, frontend::LayerSnapshot, frontend::LayerHierarchy::TraversalPathHash> diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c75c9f5001..6c1c9c1aa8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -6747,14 +6747,24 @@ void SurfaceFlinger::dumpOffscreenLayersProto(perfetto::protos::LayersProto& lay rootProto->set_name("Offscreen Root"); rootProto->set_parent(-1); - for (Layer* offscreenLayer : mOffscreenLayers) { - // Add layer as child of the fake root - rootProto->add_children(offscreenLayer->sequence); + perfetto::protos::LayersProto offscreenLayers = + LayerProtoFromSnapshotGenerator(mLayerSnapshotBuilder, mFrontEndDisplayInfos, + mLegacyLayers, traceFlags) + .generate(mLayerHierarchyBuilder.getOffscreenHierarchy()); - // Add layer - auto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags); - layerProto->set_parent(offscreenRootLayerId); + for (int i = 0; i < offscreenLayers.layers_size(); i++) { + perfetto::protos::LayerProto* layerProto = offscreenLayers.mutable_layers()->Mutable(i); + if (layerProto->parent() == -1) { + layerProto->set_parent(offscreenRootLayerId); + // Add layer as child of the fake root + rootProto->add_children(layerProto->id()); + } } + + layersProto.mutable_layers()->Reserve(layersProto.layers_size() + + offscreenLayers.layers_size()); + std::copy(offscreenLayers.layers().begin(), offscreenLayers.layers().end(), + RepeatedFieldBackInserter(layersProto.mutable_layers())); } perfetto::protos::LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 65bfce2c55..b128fb756e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1183,7 +1183,8 @@ private: perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const REQUIRES(kMainThreadContext); void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, - uint32_t traceFlags = LayerTracing::TRACE_ALL) const; + uint32_t traceFlags = LayerTracing::TRACE_ALL) const + REQUIRES(kMainThreadContext); google::protobuf::RepeatedPtrField<perfetto::protos::DisplayProto> dumpDisplayProto() const; void doActiveLayersTracingIfNeeded(bool isCompositionComputed, bool visibleRegionDirty, TimePoint, VsyncId) REQUIRES(kMainThreadContext); |