SF: LayerSnapshotBuilder updates
- Adds support for framerate, gamemode, transformhint & input
- Fixes z-order traversal bug where a layer was visited twice.
- Compat fix, a layer cannot be root once its parented
Test: presubmit
Bug: 238781169
Change-Id: Ic33aa09b2c41fadd4872ca481b41f86400629fc8
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
index 33c9440..783df28 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
@@ -562,4 +562,83 @@
hierarchyBuilder.getHierarchy().traverseInZOrder(checkTraversalPathIdVisitor);
}
+TEST_F(LayerHierarchyTest, zorderRespectsLayerSequenceId) {
+ // remove default hierarchy
+ mLifecycleManager = LayerLifecycleManager();
+ createRootLayer(1);
+ createRootLayer(2);
+ createRootLayer(4);
+ createRootLayer(5);
+ createLayer(11, 1);
+ createLayer(51, 5);
+ createLayer(53, 5);
+
+ mLifecycleManager.commitChanges();
+ LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+ std::vector<uint32_t> expectedTraversalPath = {1, 11, 2, 4, 5, 51, 53};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+
+ // A new layer is added with a smaller sequence id. Make sure its sorted correctly. While
+ // sequence ids are always incremented, this scenario can happen when a layer is reparented.
+ createRootLayer(3);
+ createLayer(52, 5);
+
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+ expectedTraversalPath = {1, 11, 2, 3, 4, 5, 51, 52, 53};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+}
+
+TEST_F(LayerHierarchyTest, zorderRespectsLayerZ) {
+ // remove default hierarchy
+ mLifecycleManager = LayerLifecycleManager();
+ createRootLayer(1);
+ createLayer(11, 1);
+ createLayer(12, 1);
+ createLayer(13, 1);
+ setZ(11, -1);
+ setZ(12, 2);
+ setZ(13, 1);
+
+ mLifecycleManager.commitChanges();
+ LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+ std::vector<uint32_t> expectedTraversalPath = {1, 11, 13, 12};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+
+ expectedTraversalPath = {11, 1, 13, 12};
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+}
+
+TEST_F(LayerHierarchyTest, zorderRespectsLayerStack) {
+ // remove default hierarchy
+ mLifecycleManager = LayerLifecycleManager();
+ createRootLayer(1);
+ createRootLayer(2);
+ createLayer(11, 1);
+ createLayer(21, 2);
+ setLayerStack(1, 20);
+ setLayerStack(2, 10);
+
+ mLifecycleManager.commitChanges();
+ LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+ std::vector<uint32_t> expectedTraversalPath = {1, 11, 2, 21};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+
+ expectedTraversalPath = {1, 11, 2, 21};
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index 08727f2..1a82232 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -245,6 +245,18 @@
mLifecycleManager.applyTransactions(transactions);
}
+ void setLayerStack(uint32_t id, int32_t layerStack) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eLayerStackChanged;
+ transactions.back().states.front().state.surface = mHandles[id];
+ transactions.back().states.front().state.layerId = static_cast<int32_t>(id);
+ transactions.back().states.front().state.layerStack = ui::LayerStack::fromValue(layerStack);
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
LayerLifecycleManager mLifecycleManager;
std::unordered_map<uint32_t, sp<LayerHandle>> mHandles;
};
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 2441c06..e124342 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -38,6 +38,9 @@
namespace android::surfaceflinger::frontend {
+using ftl::Flags;
+using namespace ftl::flag_operators;
+
// To run test:
/**
mp :libsurfaceflinger_unittest && adb sync; adb shell \
@@ -88,14 +91,11 @@
ASSERT_TRUE(expectedBuilder.getSnapshots().size() > 0);
ASSERT_TRUE(actualBuilder.getSnapshots().size() > 0);
- std::vector<std::unique_ptr<LayerSnapshot>>& snapshots = actualBuilder.getSnapshots();
std::vector<uint32_t> actualVisibleLayerIdsInZOrder;
- for (auto& snapshot : snapshots) {
- if (!snapshot->isVisible) {
- break;
- }
- actualVisibleLayerIdsInZOrder.push_back(snapshot->path.id);
- }
+ actualBuilder.forEachVisibleSnapshot(
+ [&actualVisibleLayerIdsInZOrder](const LayerSnapshot& snapshot) {
+ actualVisibleLayerIdsInZOrder.push_back(snapshot.path.id);
+ });
EXPECT_EQ(expectedVisibleLayerIdsInZOrder, actualVisibleLayerIdsInZOrder);
}
@@ -103,7 +103,6 @@
LayerHierarchyBuilder mHierarchyBuilder{{}};
LayerSnapshotBuilder mSnapshotBuilder;
- std::unordered_map<uint32_t, sp<LayerHandle>> mHandles;
display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> mFrontEndDisplayInfos;
renderengine::ShadowSettings globalShadowSettings;
static const std::vector<uint32_t> STARTING_ZORDER;
@@ -257,4 +256,54 @@
EXPECT_EQ(getSnapshot(1)->changes, RequestedLayerState::Changes::Content);
}
+TEST_F(LayerSnapshotTest, GameMode) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eMetadataChanged;
+ transactions.back().states.front().state.metadata = LayerMetadata();
+ transactions.back().states.front().state.metadata.setInt32(METADATA_GAME_MODE, 42);
+ transactions.back().states.front().state.surface = mHandles[1];
+ transactions.back().states.front().state.layerId = static_cast<int32_t>(1);
+ mLifecycleManager.applyTransactions(transactions);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(static_cast<int32_t>(getSnapshot(1)->gameMode), 42);
+ EXPECT_EQ(static_cast<int32_t>(getSnapshot(11)->gameMode), 42);
+}
+
+TEST_F(LayerSnapshotTest, NoLayerVoteForParentWithChildVotes) {
+ // ROOT
+ // ├── 1
+ // │ ├── 11 (frame rate set)
+ // │ │ └── 111
+ // │ ├── 12
+ // │ │ ├── 121
+ // │ │ └── 122
+ // │ │ └── 1221
+ // │ └── 13
+ // └── 2
+
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eFrameRateChanged;
+ transactions.back().states.front().state.frameRate = 90.0;
+ transactions.back().states.front().state.frameRateCompatibility =
+ ANATIVEWINDOW_FRAME_RATE_EXACT;
+ transactions.back().states.front().state.changeFrameRateStrategy =
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS;
+ transactions.back().states.front().state.surface = mHandles[11];
+ transactions.back().states.front().state.layerId = static_cast<int32_t>(11);
+ mLifecycleManager.applyTransactions(transactions);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+ EXPECT_EQ(getSnapshot(11)->frameRate.rate.getIntValue(), 90);
+ EXPECT_EQ(getSnapshot(11)->frameRate.type, scheduler::LayerInfo::FrameRateCompatibility::Exact);
+ EXPECT_EQ(getSnapshot(111)->frameRate.rate.getIntValue(), 90);
+ EXPECT_EQ(getSnapshot(111)->frameRate.type,
+ scheduler::LayerInfo::FrameRateCompatibility::Exact);
+ EXPECT_EQ(getSnapshot(1)->frameRate.rate.getIntValue(), 0);
+ EXPECT_EQ(getSnapshot(1)->frameRate.type, scheduler::LayerInfo::FrameRateCompatibility::NoVote);
+}
+
} // namespace android::surfaceflinger::frontend