CE: Snapshot layer metadata
Adds LayerMetadata to LayerSnapshots. LayerMetadata is only populated
when CE enables the new feature flag and the feature flag will only be
enabled in ARC++'s CE.
This change is necessary to split LayerFE from the Layer class as
ARC++'s LayerFE subclass accesses LayerMetadata.
Bug: 238781169
Test: go/wm-smoke
Test: presubmit
Change-Id: Iae405707897eedf5af9025fe628c1cd60b596e10
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index dec14d0..4469df0 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -109,6 +109,7 @@
"SurfaceFlinger_SetDisplayStateTest.cpp",
"SurfaceFlinger_SetPowerModeInternalTest.cpp",
"SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
+ "SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp",
"SchedulerTest.cpp",
"SetFrameRateTest.cpp",
"RefreshRateConfigsTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp
new file mode 100644
index 0000000..0cf3bdf
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp
@@ -0,0 +1,212 @@
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <gui/LayerMetadata.h>
+
+#include "TestableSurfaceFlinger.h"
+#include "mock/MockEventThread.h"
+#include "mock/MockVsyncController.h"
+
+namespace android {
+
+using testing::_;
+using testing::Return;
+using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
+
+class SurfaceFlingerUpdateLayerMetadataSnapshotTest : public testing::Test {
+public:
+ SurfaceFlingerUpdateLayerMetadataSnapshotTest() { setupScheduler(); }
+
+protected:
+ void setupScheduler() {
+ auto eventThread = std::make_unique<mock::EventThread>();
+ auto sfEventThread = std::make_unique<mock::EventThread>();
+
+ EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*eventThread, createEventConnection(_, _))
+ .WillOnce(Return(sp<EventThreadConnection>::make(eventThread.get(),
+ mock::EventThread::kCallingUid,
+ ResyncCallback())));
+
+ EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
+ .WillOnce(Return(sp<EventThreadConnection>::make(sfEventThread.get(),
+ mock::EventThread::kCallingUid,
+ ResyncCallback())));
+
+ auto vsyncController = std::make_unique<mock::VsyncController>();
+ auto vsyncTracker = std::make_unique<mock::VSyncTracker>();
+
+ EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*vsyncTracker, currentPeriod())
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
+ EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
+ mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
+ std::move(eventThread), std::move(sfEventThread));
+ }
+
+ sp<Layer> createLayer(const char* name, LayerMetadata layerMetadata) {
+ return sp<Layer>::make(
+ LayerCreationArgs{mFlinger.flinger(), nullptr, name, 0, layerMetadata});
+ }
+
+ TestableSurfaceFlinger mFlinger;
+};
+
+class LayerMetadataBuilder {
+public:
+ LayerMetadataBuilder(LayerMetadata layerMetadata = {}) : mLayerMetadata(layerMetadata) {}
+
+ LayerMetadataBuilder& setInt32(uint32_t key, int32_t value) {
+ mLayerMetadata.setInt32(key, value);
+ return *this;
+ }
+
+ LayerMetadata build() { return mLayerMetadata; }
+
+private:
+ LayerMetadata mLayerMetadata;
+};
+
+bool operator==(const LayerMetadata& lhs, const LayerMetadata& rhs) {
+ return lhs.mMap == rhs.mMap;
+}
+
+std::ostream& operator<<(std::ostream& stream, const LayerMetadata& layerMetadata) {
+ stream << "LayerMetadata{";
+ for (auto it = layerMetadata.mMap.cbegin(); it != layerMetadata.mMap.cend(); it++) {
+ if (it != layerMetadata.mMap.cbegin()) {
+ stream << ", ";
+ }
+ stream << layerMetadata.itemToString(it->first, ":");
+ }
+ return stream << "}";
+}
+
+// Test that the snapshot's layer metadata is set.
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest, updatesSnapshotMetadata) {
+ auto layerMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 1).build();
+ auto layer = createLayer("layer", layerMetadata);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layer);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ ASSERT_EQ(layer->getLayerSnapshot()->layerMetadata, layerMetadata);
+}
+
+// Test that snapshot layer metadata is set by merging the child's metadata on top of its
+// parent's metadata.
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest, mergesSnapshotMetadata) {
+ auto layerAMetadata = LayerMetadataBuilder()
+ .setInt32(METADATA_OWNER_UID, 1)
+ .setInt32(METADATA_TASK_ID, 2)
+ .build();
+ auto layerA = createLayer("parent", layerAMetadata);
+ auto layerBMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 3).build();
+ auto layerB = createLayer("child", layerBMetadata);
+ layerA->addChild(layerB);
+ layerA->commitChildList();
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerA);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ ASSERT_EQ(layerA->getLayerSnapshot()->layerMetadata, layerAMetadata);
+ auto expectedChildMetadata =
+ LayerMetadataBuilder(layerAMetadata).setInt32(METADATA_TASK_ID, 3).build();
+ ASSERT_EQ(layerB->getLayerSnapshot()->layerMetadata, expectedChildMetadata);
+}
+
+// Test that snapshot relative layer metadata is set to the parent's layer metadata merged on top of
+// that parent's relative layer metadata.
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest, updatesRelativeMetadata) {
+ auto layerAMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 1).build();
+ auto layerA = createLayer("relative-parent", layerAMetadata);
+ auto layerAHandle = layerA->getHandle();
+ auto layerBMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 2).build();
+ auto layerB = createLayer("relative-child", layerBMetadata);
+ layerB->setRelativeLayer(layerAHandle, 1);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerA);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerB);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ ASSERT_EQ(layerA->getLayerSnapshot()->relativeLayerMetadata, LayerMetadata{});
+ ASSERT_EQ(layerB->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+}
+
+// Test that snapshot relative layer metadata is set correctly when a layer is interleaved within
+// two other layers.
+//
+// Layer
+// A
+// / \
+// B D
+// /
+// C
+//
+// Z-order Relatives
+// B <- D <- C
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest, updatesRelativeMetadataInterleaved) {
+ auto layerAMetadata = LayerMetadataBuilder().setInt32(METADATA_OWNER_UID, 1).build();
+ auto layerA = createLayer("layer-a", layerAMetadata);
+ auto layerBMetadata = LayerMetadataBuilder()
+ .setInt32(METADATA_TASK_ID, 2)
+ .setInt32(METADATA_OWNER_PID, 3)
+ .build();
+ auto layerB = createLayer("layer-b", layerBMetadata);
+ auto layerBHandle = layerB->getHandle();
+ auto layerC = createLayer("layer-c", {});
+ auto layerDMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 4).build();
+ auto layerD = createLayer("layer-d", layerDMetadata);
+ auto layerDHandle = layerD->getHandle();
+ layerB->addChild(layerC);
+ layerA->addChild(layerB);
+ layerA->addChild(layerD);
+ layerC->setRelativeLayer(layerDHandle, 1);
+ layerD->setRelativeLayer(layerBHandle, 1);
+ layerA->commitChildList();
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerA);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ auto expectedLayerDRelativeMetadata = LayerMetadataBuilder()
+ // From layer A, parent of relative parent
+ .setInt32(METADATA_OWNER_UID, 1)
+ // From layer B, relative parent
+ .setInt32(METADATA_TASK_ID, 2)
+ .setInt32(METADATA_OWNER_PID, 3)
+ .build();
+ ASSERT_EQ(layerD->getLayerSnapshot()->relativeLayerMetadata, expectedLayerDRelativeMetadata);
+ auto expectedLayerCRelativeMetadata =
+ LayerMetadataBuilder()
+ // From layer A, parent of relative parent
+ .setInt32(METADATA_OWNER_UID, 1)
+ // From layer B, relative parent of relative parent
+ .setInt32(METADATA_OWNER_PID, 3)
+ // From layer D, relative parent
+ .setInt32(METADATA_TASK_ID, 4)
+ .build();
+ ASSERT_EQ(layerC->getLayerSnapshot()->relativeLayerMetadata, expectedLayerCRelativeMetadata);
+}
+
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest,
+ updatesRelativeMetadataMultipleRelativeChildren) {
+ auto layerAMetadata = LayerMetadataBuilder().setInt32(METADATA_OWNER_UID, 1).build();
+ auto layerA = createLayer("layer-a", layerAMetadata);
+ auto layerAHandle = layerA->getHandle();
+ auto layerB = createLayer("layer-b", {});
+ auto layerC = createLayer("layer-c", {});
+ layerB->setRelativeLayer(layerAHandle, 1);
+ layerC->setRelativeLayer(layerAHandle, 2);
+ layerA->commitChildList();
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerA);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerB);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerC);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ ASSERT_EQ(layerA->getLayerSnapshot()->relativeLayerMetadata, LayerMetadata{});
+ ASSERT_EQ(layerB->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+ ASSERT_EQ(layerC->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 2c9c451..13389a1 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -477,6 +477,8 @@
return mFlinger->mirrorLayer(args, mirrorFromHandle, outHandle, outLayerId);
}
+ void updateLayerMetadataSnapshot() { mFlinger->updateLayerMetadataSnapshot(); }
+
/* ------------------------------------------------------------------------
* Read-only access to private data to assert post-conditions.
*/