diff options
author | 2023-03-16 18:52:15 +0000 | |
---|---|---|
committer | 2023-03-16 18:52:15 +0000 | |
commit | d018360181d2efe669e1fc25426ac91f3389847b (patch) | |
tree | c99d577fc3bc0eeeb478df27b6424b9374f74649 | |
parent | d19848fcab877e614ee3a4124fa3df9da45ea55a (diff) |
[LayerTraceGenerator] fix mirrors and rel-z data
relanding: actual regression was fixed here: Id58a41b46b4d03dc6d69259220c04e2f341be4fd and was not caused by this cl
Now that we are using the new front end to
generate layers trace, we need to make a few fixes
so we can generate data that's parsable by winscope.
This means use a unique id instead of the layer id to
identify layers.
Test: presubmit
Fixes: 255901752
Change-Id: Ife768ada07940f298a0a7b1ff81d95901559c57c
-rw-r--r-- | services/surfaceflinger/FrontEnd/LayerHierarchy.h | 10 | ||||
-rw-r--r-- | services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 11 | ||||
-rw-r--r-- | services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h | 14 | ||||
-rw-r--r-- | services/surfaceflinger/LayerProtoHelper.cpp | 111 | ||||
-rw-r--r-- | services/surfaceflinger/LayerProtoHelper.h | 41 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 14 | ||||
-rw-r--r-- | services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp | 25 | ||||
-rw-r--r-- | services/surfaceflinger/layerproto/layers.proto | 2 | ||||
-rw-r--r-- | services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp | 20 |
9 files changed, 160 insertions, 88 deletions
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h index 3dd89badff..b25b731356 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h @@ -104,6 +104,16 @@ public: static const TraversalPath ROOT; }; + struct TraversalPathHash { + std::size_t operator()(const LayerHierarchy::TraversalPath& key) const { + uint32_t hashCode = key.id * 31; + if (key.mirrorRootId != UNASSIGNED_LAYER_ID) { + hashCode += key.mirrorRootId * 31; + } + return std::hash<size_t>{}(hashCode); + } + }; + // Helper class to add nodes to an existing traversal id and removes the // node when it goes out of scope. class ScopedAddToTraversalPath { diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 8a450933f0..5e7c25946b 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -28,9 +28,14 @@ LayerSnapshot::LayerSnapshot(const RequestedLayerState& state, const LayerHierarchy::TraversalPath& path) : path(path) { static uint32_t sUniqueSequenceId = 0; - // Provide a unique id for clones otherwise keeping using the sequence id. - // The seq id can still be useful for debugging if its available. - uniqueSequence = (path.isClone()) ? sUniqueSequenceId++ : state.id; + // Provide a unique id for all snapshots. + // A front end layer can generate multiple snapshots if its mirrored. + // Additionally, if the layer is not reachable, we may choose to destroy + // and recreate the snapshot in which case the unique sequence id will + // change. The consumer shouldn't tie any lifetimes to this unique id but + // register a LayerLifecycleManager::ILifecycleListener or get a list of + // destroyed layers from LayerLifecycleManager. + uniqueSequence = sUniqueSequenceId++; sequence = static_cast<int32_t>(state.id); name = state.name; textureName = state.textureName; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h index 3997a0ad83..7b1ff2710b 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h @@ -68,6 +68,7 @@ public: void update(const Args&); std::vector<std::unique_ptr<LayerSnapshot>>& getSnapshots(); LayerSnapshot* getSnapshot(uint32_t layerId) const; + LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath& id) const; typedef std::function<void(const LayerSnapshot& snapshot)> ConstVisitor; @@ -86,7 +87,6 @@ public: private: friend class LayerSnapshotTest; - LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath& id) const; static LayerSnapshot getRootSnapshot(); // return true if we were able to successfully update the snapshots via @@ -120,16 +120,8 @@ private: void updateChildState(LayerSnapshot& snapshot, const LayerSnapshot& childSnapshot, const Args& args); - struct TraversalPathHash { - std::size_t operator()(const LayerHierarchy::TraversalPath& key) const { - uint32_t hashCode = key.id * 31; - if (key.mirrorRootId != UNASSIGNED_LAYER_ID) { - hashCode += key.mirrorRootId * 31; - } - return std::hash<size_t>{}(hashCode); - } - }; - std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*, TraversalPathHash> + std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*, + LayerHierarchy::TraversalPathHash> mIdToSnapshot; std::vector<std::unique_ptr<LayerSnapshot>> mSnapshots; LayerSnapshot mRootSnapshot; diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 5c91b9181b..b5ae1a7f5a 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -15,6 +15,8 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues +#include "FrontEnd/LayerCreationArgs.h" +#include "FrontEnd/LayerSnapshot.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wextra" @@ -248,47 +250,88 @@ void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegio outRegion.bottom = proto.bottom(); } -void LayerProtoHelper::writeHierarchyToProto( - LayersProto& outLayersProto, const frontend::LayerHierarchy& root, - const frontend::LayerSnapshotBuilder& snapshotBuilder, - const std::unordered_map<uint32_t, sp<Layer>>& legacyLayers, uint32_t traceFlags) { - using Variant = frontend::LayerHierarchy::Variant; - frontend::LayerSnapshot defaultSnapshot; - - LayerProto* layerProto = outLayersProto.add_layers(); - const frontend::RequestedLayerState& layer = *root.getLayer(); - frontend::LayerSnapshot* snapshot = snapshotBuilder.getSnapshot(layer.id); +LayersProto LayerProtoFromSnapshotGenerator::generate(const frontend::LayerHierarchy& root) { + mLayersProto.clear_layers(); + std::unordered_set<uint64_t> stackIdsToSkip; + if ((mTraceFlags & LayerTracing::TRACE_VIRTUAL_DISPLAYS) == 0) { + for (const auto& [layerStack, displayInfo] : mDisplayInfos) { + if (displayInfo.isVirtual) { + stackIdsToSkip.insert(layerStack.id); + } + } + } - if (!snapshot) { - defaultSnapshot.uniqueSequence = layer.id; - snapshot = &defaultSnapshot; + frontend::LayerHierarchy::TraversalPath path = frontend::LayerHierarchy::TraversalPath::ROOT; + for (auto& [child, variant] : root.mChildren) { + if (variant != frontend::LayerHierarchy::Variant::Attached || + stackIdsToSkip.find(child->getLayer()->layerStack.id) != stackIdsToSkip.end()) { + continue; + } + frontend::LayerHierarchy::ScopedAddToTraversalPath addChildToPath(path, + child->getLayer()->id, + variant); + LayerProtoFromSnapshotGenerator::writeHierarchyToProto(*child, path); } - writeSnapshotToProto(layerProto, layer, *snapshot, traceFlags); - for (const auto& [child, variant] : root.mChildren) { - if (variant == Variant::Attached || variant == Variant::Detached) { - layerProto->add_children(child->getLayer()->id); - } else if (variant == Variant::Relative) { - layerProto->add_relatives(child->getLayer()->id); + + // fill in relative and parent info + for (int i = 0; i < mLayersProto.layers_size(); i++) { + auto layerProto = mLayersProto.mutable_layers()->Mutable(i); + auto it = mChildToRelativeParent.find(layerProto->id()); + if (it == mChildToRelativeParent.end()) { + layerProto->set_z_order_relative_of(-1); + } else { + layerProto->set_z_order_relative_of(it->second); + } + it = mChildToParent.find(layerProto->id()); + if (it == mChildToParent.end()) { + layerProto->set_parent(-1); + } else { + layerProto->set_parent(it->second); } } - auto parent = root.getParent(); - if (parent && parent->getLayer()) { - layerProto->set_parent(parent->getLayer()->id); + mDefaultSnapshots.clear(); + mChildToRelativeParent.clear(); + return std::move(mLayersProto); +} + +frontend::LayerSnapshot* LayerProtoFromSnapshotGenerator::getSnapshot( + frontend::LayerHierarchy::TraversalPath& path, const frontend::RequestedLayerState& layer) { + frontend::LayerSnapshot* snapshot = mSnapshotBuilder.getSnapshot(path); + if (snapshot) { + return snapshot; } else { - layerProto->set_parent(-1); + mDefaultSnapshots[path] = frontend::LayerSnapshot(layer, path); + return &mDefaultSnapshots[path]; } +} - auto relativeParent = root.getRelativeParent(); - if (relativeParent && relativeParent->getLayer()) { - layerProto->set_z_order_relative_of(relativeParent->getLayer()->id); - } else { - layerProto->set_z_order_relative_of(-1); +void LayerProtoFromSnapshotGenerator::writeHierarchyToProto( + const frontend::LayerHierarchy& root, frontend::LayerHierarchy::TraversalPath& path) { + using Variant = frontend::LayerHierarchy::Variant; + LayerProto* layerProto = mLayersProto.add_layers(); + const frontend::RequestedLayerState& layer = *root.getLayer(); + frontend::LayerSnapshot* snapshot = getSnapshot(path, layer); + LayerProtoHelper::writeSnapshotToProto(layerProto, layer, *snapshot, mTraceFlags); + + for (const auto& [child, variant] : root.mChildren) { + frontend::LayerHierarchy::ScopedAddToTraversalPath addChildToPath(path, + child->getLayer()->id, + variant); + frontend::LayerSnapshot* childSnapshot = getSnapshot(path, layer); + if (variant == Variant::Attached || variant == Variant::Detached || + variant == Variant::Mirror) { + mChildToParent[childSnapshot->uniqueSequence] = snapshot->uniqueSequence; + layerProto->add_children(childSnapshot->uniqueSequence); + } else if (variant == Variant::Relative) { + mChildToRelativeParent[childSnapshot->uniqueSequence] = snapshot->uniqueSequence; + layerProto->add_relatives(childSnapshot->uniqueSequence); + } } - if (traceFlags & LayerTracing::TRACE_COMPOSITION) { - auto it = legacyLayers.find(layer.id); - if (it != legacyLayers.end()) { + if (mTraceFlags & LayerTracing::TRACE_COMPOSITION) { + auto it = mLegacyLayers.find(layer.id); + if (it != mLegacyLayers.end()) { it->second->writeCompositionStateToProto(layerProto); } } @@ -298,7 +341,10 @@ void LayerProtoHelper::writeHierarchyToProto( if (variant == Variant::Detached) { continue; } - writeHierarchyToProto(outLayersProto, *child, snapshotBuilder, legacyLayers, traceFlags); + frontend::LayerHierarchy::ScopedAddToTraversalPath addChildToPath(path, + child->getLayer()->id, + variant); + writeHierarchyToProto(*child, path); } } @@ -345,6 +391,7 @@ void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, layerInfo->set_shadow_radius(snapshot.shadowRadius); layerInfo->set_id(snapshot.uniqueSequence); + layerInfo->set_original_id(snapshot.sequence); layerInfo->set_name(requestedState.name); layerInfo->set_type("Layer"); diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 38d73f613f..b84a49b27c 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -25,6 +25,9 @@ #include <ui/Rect.h> #include <ui/Region.h> #include <ui/Transform.h> +#include <cstdint> +#include "FrontEnd/LayerHierarchy.h" +#include "FrontEnd/LayerSnapshot.h" namespace android { namespace surfaceflinger { @@ -58,11 +61,6 @@ public: static void readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix); static void writeToProto(const android::BlurRegion region, BlurRegion*); static void readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion); - static void writeHierarchyToProto(LayersProto& layersProto, - const frontend::LayerHierarchy& root, - const frontend::LayerSnapshotBuilder& snapshotBuilder, - const std::unordered_map<uint32_t, sp<Layer>>& mLegacyLayers, - uint32_t traceFlags); static void writeSnapshotToProto(LayerProto* outProto, const frontend::RequestedLayerState& requestedState, const frontend::LayerSnapshot& snapshot, uint32_t traceFlags); @@ -70,5 +68,38 @@ public: const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displayInfos); }; +class LayerProtoFromSnapshotGenerator { +public: + LayerProtoFromSnapshotGenerator( + const frontend::LayerSnapshotBuilder& snapshotBuilder, + const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displayInfos, + const std::unordered_map<uint32_t, sp<Layer>>& legacyLayers, uint32_t traceFlags) + : mSnapshotBuilder(snapshotBuilder), + mLegacyLayers(legacyLayers), + mDisplayInfos(displayInfos), + mTraceFlags(traceFlags) {} + LayersProto generate(const frontend::LayerHierarchy& root); + +private: + void writeHierarchyToProto(const frontend::LayerHierarchy& root, + frontend::LayerHierarchy::TraversalPath& path); + frontend::LayerSnapshot* getSnapshot(frontend::LayerHierarchy::TraversalPath& path, + const frontend::RequestedLayerState& layer); + + const frontend::LayerSnapshotBuilder& mSnapshotBuilder; + const std::unordered_map<uint32_t, sp<Layer>>& mLegacyLayers; + const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& mDisplayInfos; + uint32_t mTraceFlags; + LayersProto mLayersProto; + // 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> + mDefaultSnapshots; + std::unordered_map<uint32_t /* child unique seq*/, uint32_t /* relative parent unique seq*/> + mChildToRelativeParent; + std::unordered_map<uint32_t /* child unique seq*/, uint32_t /* parent unique seq*/> + mChildToParent; +}; + } // namespace surfaceflinger } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e47a147ed8..01a7df398b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5786,17 +5786,9 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { return layersProto; } - const frontend::LayerHierarchy& root = mLayerHierarchyBuilder.getHierarchy(); - LayersProto layersProto; - for (auto& [child, variant] : root.mChildren) { - if (variant != frontend::LayerHierarchy::Variant::Attached || - stackIdsToSkip.find(child->getLayer()->layerStack.id) != stackIdsToSkip.end()) { - continue; - } - LayerProtoHelper::writeHierarchyToProto(layersProto, *child, mLayerSnapshotBuilder, - mLegacyLayers, traceFlags); - } - return layersProto; + return LayerProtoFromSnapshotGenerator(mLayerSnapshotBuilder, mFrontEndDisplayInfos, {}, + traceFlags) + .generate(mLayerHierarchyBuilder.getHierarchy()); } google::protobuf::RepeatedPtrField<DisplayProto> SurfaceFlinger::dumpDisplayProto() const { diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp index 0a7101ccce..2418cf22e5 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp @@ -134,29 +134,10 @@ bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile, lifecycleManager.getGlobalChanges().string().c_str()); lifecycleManager.commitChanges(); - // write layers trace - auto tracingFlags = LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS; - std::unordered_set<uint64_t> stackIdsToSkip; - if ((tracingFlags & LayerTracing::TRACE_VIRTUAL_DISPLAYS) == 0) { - for (const auto& displayInfo : displayInfos) { - if (displayInfo.second.isVirtual) { - stackIdsToSkip.insert(displayInfo.first.id); - } - } - } - - const frontend::LayerHierarchy& root = hierarchyBuilder.getHierarchy(); - - LayersProto layersProto; - for (auto& [child, variant] : root.mChildren) { - if (variant != frontend::LayerHierarchy::Variant::Attached || - stackIdsToSkip.find(child->getLayer()->layerStack.id) != stackIdsToSkip.end()) { - continue; - } - LayerProtoHelper::writeHierarchyToProto(layersProto, *child, snapshotBuilder, {}, - tracingFlags); - } + LayersProto layersProto = LayerProtoFromSnapshotGenerator(snapshotBuilder, displayInfos, {}, + layerTracing.getFlags()) + .generate(hierarchyBuilder.getHierarchy()); auto displayProtos = LayerProtoHelper::writeDisplayInfoToProto(displayInfos); layerTracing.notify(visibleRegionsDirty, entry.elapsed_realtime_nanos(), entry.vsync_id(), &layersProto, {}, &displayProtos); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 3598308338..e9add2e1a4 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -138,6 +138,8 @@ message LayerProto { float requested_corner_radius = 56; RectProto destination_frame = 57; + + uint32 original_id = 58; } message PositionProto { diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp index 5f9214c548..7355c35131 100644 --- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp +++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp @@ -20,6 +20,7 @@ #include <fstream> #include <iostream> #include <string> +#include <unordered_map> #include <LayerTraceGenerator.h> #include <Tracing/TransactionProtoParser.h> @@ -84,9 +85,9 @@ protected: std::vector<std::filesystem::path> TransactionTraceTestSuite::sTransactionTraces{}; struct LayerInfo { - int id; + int32_t id; std::string name; - int parent; + int32_t parent; int z; uint64_t curr_frame; float x; @@ -143,16 +144,27 @@ TEST_P(TransactionTraceTestSuite, validateEndState) { expectedLayers.reserve(static_cast<size_t>(expectedLastEntry.layers().layers_size())); for (int i = 0; i < expectedLastEntry.layers().layers_size(); i++) { auto layer = expectedLastEntry.layers().layers(i); - expectedLayers.push_back(getLayerInfoFromProto(layer)); + LayerInfo layerInfo = getLayerInfoFromProto(layer); + expectedLayers.push_back(layerInfo); } std::sort(expectedLayers.begin(), expectedLayers.end(), compareById); + std::unordered_map<int32_t /* snapshotId*/, int32_t /*layerId*/> snapshotIdToLayerId; std::vector<LayerInfo> actualLayers; actualLayers.reserve(static_cast<size_t>(actualLastEntry.layers().layers_size())); for (int i = 0; i < actualLastEntry.layers().layers_size(); i++) { auto layer = actualLastEntry.layers().layers(i); - actualLayers.push_back(getLayerInfoFromProto(layer)); + LayerInfo layerInfo = getLayerInfoFromProto(layer); + snapshotIdToLayerId[layerInfo.id] = static_cast<int32_t>(layer.original_id()); + actualLayers.push_back(layerInfo); + } + + for (auto& layer : actualLayers) { + layer.id = snapshotIdToLayerId[layer.id]; + auto it = snapshotIdToLayerId.find(layer.parent); + layer.parent = it == snapshotIdToLayerId.end() ? -1 : it->second; } + std::sort(actualLayers.begin(), actualLayers.end(), compareById); size_t i = 0; |