SF: Introduce LayerSnapshot and LayerSnapshotBuilder

Create a builder that walks through the layer hierarchy
to build an ordered list of LayerSnapshots that can be
passed on to CompositionEngine.

This builder does a minimum amount of work to update
an existing set of snapshots based on hierarchy changes
and RequestedLayerState changes.

The builder also introduces a fast path to update
snapshots when there are only buffer updates.

Additionally, pull out LayerSnapshot class from LayerFE
and move it to frontend package.

Bug: 238781169
Test: presubmit
Change-Id: I3fbd6d60968950df2ee97d975c72f9e0aa31b007
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 7bccfa7..c46806c 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -95,6 +95,7 @@
         "LayerMetadataTest.cpp",
         "LayerHierarchyTest.cpp",
         "LayerLifecycleManagerTest.cpp",
+        "LayerSnapshotTest.cpp",
         "LayerTest.cpp",
         "LayerTestUtils.cpp",
         "MessageQueueTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
index 8560902..33c9440 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
@@ -21,6 +21,7 @@
 #include "FrontEnd/LayerHierarchy.h"
 #include "FrontEnd/LayerLifecycleManager.h"
 #include "Layer.h"
+#include "LayerHierarchyTest.h"
 #include "gui/SurfaceComposerClient.h"
 
 #define UPDATE_AND_VERIFY(HIERARCHY)  \
@@ -31,16 +32,6 @@
 
 namespace android::surfaceflinger::frontend {
 
-namespace {
-LayerCreationArgs createArgs(uint32_t id, bool canBeRoot, wp<IBinder> parent, wp<IBinder> mirror) {
-    LayerCreationArgs args(nullptr, nullptr, "testlayer", 0, {}, std::make_optional(id));
-    args.addToRoot = canBeRoot;
-    args.parentHandle = parent;
-    args.mirrorLayerHandle = mirror;
-    return args;
-}
-} // namespace
-
 // To run test:
 /**
  mp :libsurfaceflinger_unittest && adb sync; adb shell \
@@ -50,163 +41,9 @@
     --gtest_brief=1
 */
 
-class LayerHierarchyTest : public testing::Test {
+class LayerHierarchyTest : public LayerHierarchyTestBase {
 protected:
-    LayerHierarchyTest() {
-        // tree with 3 levels of children
-        // ROOT
-        // ├── 1
-        // │   ├── 11
-        // │   │   └── 111
-        // │   ├── 12
-        // │   │   ├── 121
-        // │   │   └── 122
-        // │   │       └── 1221
-        // │   └── 13
-        // └── 2
-
-        createRootLayer(1);
-        createRootLayer(2);
-        createLayer(11, 1);
-        createLayer(12, 1);
-        createLayer(13, 1);
-        createLayer(111, 11);
-        createLayer(121, 12);
-        createLayer(122, 12);
-        createLayer(1221, 122);
-        mLifecycleManager.commitChanges();
-    }
-    std::vector<uint32_t> getTraversalPath(const LayerHierarchy& hierarchy) const {
-        std::vector<uint32_t> layerIds;
-        hierarchy.traverse([&layerIds = layerIds](const LayerHierarchy& hierarchy,
-                                                  const LayerHierarchy::TraversalPath&) -> bool {
-            layerIds.emplace_back(hierarchy.getLayer()->id);
-            return true;
-        });
-        return layerIds;
-    }
-
-    std::vector<uint32_t> getTraversalPathInZOrder(const LayerHierarchy& hierarchy) const {
-        std::vector<uint32_t> layerIds;
-        hierarchy.traverseInZOrder(
-                [&layerIds = layerIds](const LayerHierarchy& hierarchy,
-                                       const LayerHierarchy::TraversalPath&) -> bool {
-                    layerIds.emplace_back(hierarchy.getLayer()->id);
-                    return true;
-                });
-        return layerIds;
-    }
-
-    void createRootLayer(uint32_t id) {
-        sp<LayerHandle> handle = sp<LayerHandle>::make(id);
-        mHandles[id] = handle;
-        std::vector<std::unique_ptr<RequestedLayerState>> layers;
-        layers.emplace_back(std::make_unique<RequestedLayerState>(
-                createArgs(/*id=*/id, /*canBeRoot=*/true, /*parent=*/nullptr, /*mirror=*/nullptr)));
-        mLifecycleManager.addLayers(std::move(layers));
-    }
-
-    void createLayer(uint32_t id, uint32_t parentId) {
-        sp<LayerHandle> handle = sp<LayerHandle>::make(id);
-        mHandles[id] = handle;
-        std::vector<std::unique_ptr<RequestedLayerState>> layers;
-        layers.emplace_back(std::make_unique<RequestedLayerState>(
-                createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/mHandles[parentId],
-                           /*mirror=*/nullptr)));
-        mLifecycleManager.addLayers(std::move(layers));
-    }
-
-    void reparentLayer(uint32_t id, uint32_t newParentId) {
-        std::vector<TransactionState> transactions;
-        transactions.emplace_back();
-        transactions.back().states.push_back({});
-
-        if (newParentId == UNASSIGNED_LAYER_ID) {
-            transactions.back().states.front().state.parentSurfaceControlForChild = nullptr;
-        } else {
-            auto parentHandle = mHandles[newParentId];
-            transactions.back().states.front().state.parentSurfaceControlForChild =
-                    sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(), parentHandle,
-                                             static_cast<int32_t>(newParentId), "Test");
-        }
-        transactions.back().states.front().state.what = layer_state_t::eReparent;
-        transactions.back().states.front().state.surface = mHandles[id];
-        mLifecycleManager.applyTransactions(transactions);
-    }
-
-    void reparentRelativeLayer(uint32_t id, uint32_t relativeParentId) {
-        std::vector<TransactionState> transactions;
-        transactions.emplace_back();
-        transactions.back().states.push_back({});
-
-        if (relativeParentId == UNASSIGNED_LAYER_ID) {
-            transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
-        } else {
-            auto parentHandle = mHandles[relativeParentId];
-            transactions.back().states.front().state.relativeLayerSurfaceControl =
-                    sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(), parentHandle,
-                                             static_cast<int32_t>(relativeParentId), "test");
-            transactions.back().states.front().state.what = layer_state_t::eRelativeLayerChanged;
-        }
-        transactions.back().states.front().state.surface = mHandles[id];
-        mLifecycleManager.applyTransactions(transactions);
-    }
-
-    void mirrorLayer(uint32_t id, uint32_t parent, uint32_t layerToMirror) {
-        auto parentHandle = (parent == UNASSIGNED_LAYER_ID) ? nullptr : mHandles[parent];
-        auto mirrorHandle =
-                (layerToMirror == UNASSIGNED_LAYER_ID) ? nullptr : mHandles[layerToMirror];
-
-        sp<LayerHandle> handle = sp<LayerHandle>::make(id);
-        mHandles[id] = handle;
-        std::vector<std::unique_ptr<RequestedLayerState>> layers;
-        layers.emplace_back(std::make_unique<RequestedLayerState>(
-                createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentHandle,
-                           /*mirror=*/mHandles[layerToMirror])));
-        mLifecycleManager.addLayers(std::move(layers));
-    }
-
-    void updateBackgroundColor(uint32_t id, half alpha) {
-        std::vector<TransactionState> transactions;
-        transactions.emplace_back();
-        transactions.back().states.push_back({});
-        transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
-        transactions.back().states.front().state.bgColorAlpha = alpha;
-        transactions.back().states.front().state.surface = mHandles[id];
-        mLifecycleManager.applyTransactions(transactions);
-    }
-
-    void destroyLayerHandle(uint32_t id) { mLifecycleManager.onHandlesDestroyed({id}); }
-
-    void updateAndVerify(LayerHierarchyBuilder& hierarchyBuilder) {
-        if (mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)) {
-            hierarchyBuilder.update(mLifecycleManager.getLayers(),
-                                    mLifecycleManager.getDestroyedLayers());
-        }
-        mLifecycleManager.commitChanges();
-
-        // rebuild layer hierarchy from scratch and verify that it matches the updated state.
-        LayerHierarchyBuilder newBuilder(mLifecycleManager.getLayers());
-        EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()),
-                  getTraversalPath(newBuilder.getHierarchy()));
-        EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()),
-                  getTraversalPathInZOrder(newBuilder.getHierarchy()));
-        EXPECT_FALSE(
-                mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
-    }
-
-    void setZ(uint32_t id, int32_t z) {
-        std::vector<TransactionState> transactions;
-        transactions.emplace_back();
-        transactions.back().states.push_back({});
-
-        transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
-        transactions.back().states.front().state.layerId = static_cast<int32_t>(id);
-        transactions.back().states.front().state.z = z;
-        mLifecycleManager.applyTransactions(transactions);
-    }
-    LayerLifecycleManager mLifecycleManager;
-    std::unordered_map<uint32_t, sp<LayerHandle>> mHandles;
+    LayerHierarchyTest() : LayerHierarchyTestBase() { mLifecycleManager.commitChanges(); }
 };
 
 // reparenting tests
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
new file mode 100644
index 0000000..08727f2
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "FrontEnd/LayerHandle.h"
+#include "FrontEnd/LayerHierarchy.h"
+#include "FrontEnd/LayerLifecycleManager.h"
+#include "Layer.h"
+#include "gui/SurfaceComposerClient.h"
+
+namespace android::surfaceflinger::frontend {
+
+class LayerHierarchyTestBase : public testing::Test {
+protected:
+    LayerHierarchyTestBase() {
+        // tree with 3 levels of children
+        // ROOT
+        // ├── 1
+        // │   ├── 11
+        // │   │   └── 111
+        // │   ├── 12
+        // │   │   ├── 121
+        // │   │   └── 122
+        // │   │       └── 1221
+        // │   └── 13
+        // └── 2
+
+        createRootLayer(1);
+        createRootLayer(2);
+        createLayer(11, 1);
+        createLayer(12, 1);
+        createLayer(13, 1);
+        createLayer(111, 11);
+        createLayer(121, 12);
+        createLayer(122, 12);
+        createLayer(1221, 122);
+    }
+
+    LayerCreationArgs createArgs(uint32_t id, bool canBeRoot, wp<IBinder> parent,
+                                 wp<IBinder> mirror) {
+        LayerCreationArgs args(nullptr, nullptr, "testlayer", 0, {}, std::make_optional(id));
+        args.addToRoot = canBeRoot;
+        args.parentHandle = parent;
+        args.mirrorLayerHandle = mirror;
+        return args;
+    }
+
+    std::vector<uint32_t> getTraversalPath(const LayerHierarchy& hierarchy) const {
+        std::vector<uint32_t> layerIds;
+        hierarchy.traverse([&layerIds = layerIds](const LayerHierarchy& hierarchy,
+                                                  const LayerHierarchy::TraversalPath&) -> bool {
+            layerIds.emplace_back(hierarchy.getLayer()->id);
+            return true;
+        });
+        return layerIds;
+    }
+
+    std::vector<uint32_t> getTraversalPathInZOrder(const LayerHierarchy& hierarchy) const {
+        std::vector<uint32_t> layerIds;
+        hierarchy.traverseInZOrder(
+                [&layerIds = layerIds](const LayerHierarchy& hierarchy,
+                                       const LayerHierarchy::TraversalPath&) -> bool {
+                    layerIds.emplace_back(hierarchy.getLayer()->id);
+                    return true;
+                });
+        return layerIds;
+    }
+
+    virtual void createRootLayer(uint32_t id) {
+        sp<LayerHandle> handle = sp<LayerHandle>::make(id);
+        mHandles[id] = handle;
+        std::vector<std::unique_ptr<RequestedLayerState>> layers;
+        layers.emplace_back(std::make_unique<RequestedLayerState>(
+                createArgs(/*id=*/id, /*canBeRoot=*/true, /*parent=*/nullptr, /*mirror=*/nullptr)));
+        mLifecycleManager.addLayers(std::move(layers));
+    }
+
+    virtual void createLayer(uint32_t id, uint32_t parentId) {
+        sp<LayerHandle> handle = sp<LayerHandle>::make(id);
+        mHandles[id] = handle;
+        std::vector<std::unique_ptr<RequestedLayerState>> layers;
+        layers.emplace_back(std::make_unique<RequestedLayerState>(
+                createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/mHandles[parentId],
+                           /*mirror=*/nullptr)));
+        mLifecycleManager.addLayers(std::move(layers));
+    }
+
+    void reparentLayer(uint32_t id, uint32_t newParentId) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+
+        if (newParentId == UNASSIGNED_LAYER_ID) {
+            transactions.back().states.front().state.parentSurfaceControlForChild = nullptr;
+        } else {
+            auto parentHandle = mHandles[newParentId];
+            transactions.back().states.front().state.parentSurfaceControlForChild =
+                    sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(), parentHandle,
+                                             static_cast<int32_t>(newParentId), "Test");
+        }
+        transactions.back().states.front().state.what = layer_state_t::eReparent;
+        transactions.back().states.front().state.surface = mHandles[id];
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    void reparentRelativeLayer(uint32_t id, uint32_t relativeParentId) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+
+        if (relativeParentId == UNASSIGNED_LAYER_ID) {
+            transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
+        } else {
+            auto parentHandle = mHandles[relativeParentId];
+            transactions.back().states.front().state.relativeLayerSurfaceControl =
+                    sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(), parentHandle,
+                                             static_cast<int32_t>(relativeParentId), "test");
+            transactions.back().states.front().state.what = layer_state_t::eRelativeLayerChanged;
+        }
+        transactions.back().states.front().state.surface = mHandles[id];
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    virtual void mirrorLayer(uint32_t id, uint32_t parent, uint32_t layerToMirror) {
+        auto parentHandle = (parent == UNASSIGNED_LAYER_ID) ? nullptr : mHandles[parent];
+        auto mirrorHandle =
+                (layerToMirror == UNASSIGNED_LAYER_ID) ? nullptr : mHandles[layerToMirror];
+
+        sp<LayerHandle> handle = sp<LayerHandle>::make(id);
+        mHandles[id] = handle;
+        std::vector<std::unique_ptr<RequestedLayerState>> layers;
+        layers.emplace_back(std::make_unique<RequestedLayerState>(
+                createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentHandle,
+                           /*mirror=*/mHandles[layerToMirror])));
+        mLifecycleManager.addLayers(std::move(layers));
+    }
+
+    void updateBackgroundColor(uint32_t id, half alpha) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+        transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
+        transactions.back().states.front().state.bgColorAlpha = alpha;
+        transactions.back().states.front().state.surface = mHandles[id];
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    void destroyLayerHandle(uint32_t id) { mLifecycleManager.onHandlesDestroyed({id}); }
+
+    void updateAndVerify(LayerHierarchyBuilder& hierarchyBuilder) {
+        if (mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)) {
+            hierarchyBuilder.update(mLifecycleManager.getLayers(),
+                                    mLifecycleManager.getDestroyedLayers());
+        }
+        mLifecycleManager.commitChanges();
+
+        // rebuild layer hierarchy from scratch and verify that it matches the updated state.
+        LayerHierarchyBuilder newBuilder(mLifecycleManager.getLayers());
+        EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()),
+                  getTraversalPath(newBuilder.getHierarchy()));
+        EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()),
+                  getTraversalPathInZOrder(newBuilder.getHierarchy()));
+        EXPECT_FALSE(
+                mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    }
+
+    void setZ(uint32_t id, int32_t z) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+
+        transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
+        transactions.back().states.front().state.surface = mHandles[id];
+        transactions.back().states.front().state.layerId = static_cast<int32_t>(id);
+        transactions.back().states.front().state.z = z;
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    void setCrop(uint32_t id, const Rect& crop) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+
+        transactions.back().states.front().state.what = layer_state_t::eCropChanged;
+        transactions.back().states.front().state.surface = mHandles[id];
+        transactions.back().states.front().state.layerId = static_cast<int32_t>(id);
+        transactions.back().states.front().state.crop = crop;
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    void setFlags(uint32_t id, uint32_t mask, uint32_t flags) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+
+        transactions.back().states.front().state.what = layer_state_t::eFlagsChanged;
+        transactions.back().states.front().state.flags = flags;
+        transactions.back().states.front().state.mask = mask;
+        transactions.back().states.front().state.surface = mHandles[id];
+        transactions.back().states.front().state.layerId = static_cast<int32_t>(id);
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    void setAlpha(uint32_t id, float alpha) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+
+        transactions.back().states.front().state.what = layer_state_t::eAlphaChanged;
+        transactions.back().states.front().state.surface = mHandles[id];
+        transactions.back().states.front().state.layerId = static_cast<int32_t>(id);
+        transactions.back().states.front().state.color.a = static_cast<half>(alpha);
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    void hideLayer(uint32_t id) {
+        setFlags(id, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
+    }
+
+    void showLayer(uint32_t id) { setFlags(id, layer_state_t::eLayerHidden, 0); }
+
+    void setColor(uint32_t id, half3 rgb = half3(1._hf, 1._hf, 1._hf)) {
+        std::vector<TransactionState> transactions;
+        transactions.emplace_back();
+        transactions.back().states.push_back({});
+        transactions.back().states.front().state.what = layer_state_t::eColorChanged;
+        transactions.back().states.front().state.color.rgb = rgb;
+        transactions.back().states.front().state.surface = mHandles[id];
+        transactions.back().states.front().state.layerId = static_cast<int32_t>(id);
+        mLifecycleManager.applyTransactions(transactions);
+    }
+
+    LayerLifecycleManager mLifecycleManager;
+    std::unordered_map<uint32_t, sp<LayerHandle>> mHandles;
+};
+
+} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
new file mode 100644
index 0000000..2441c06
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "FrontEnd/LayerHandle.h"
+#include "FrontEnd/LayerHierarchy.h"
+#include "FrontEnd/LayerLifecycleManager.h"
+#include "FrontEnd/LayerSnapshotBuilder.h"
+#include "Layer.h"
+#include "LayerHierarchyTest.h"
+
+#define UPDATE_AND_VERIFY(BUILDER, ...)                                    \
+    ({                                                                     \
+        SCOPED_TRACE("");                                                  \
+        updateAndVerify((BUILDER), /*displayChanges=*/false, __VA_ARGS__); \
+    })
+
+#define UPDATE_AND_VERIFY_WITH_DISPLAY_CHANGES(BUILDER, ...)              \
+    ({                                                                    \
+        SCOPED_TRACE("");                                                 \
+        updateAndVerify((BUILDER), /*displayChanges=*/true, __VA_ARGS__); \
+    })
+
+namespace android::surfaceflinger::frontend {
+
+// To run test:
+/**
+ mp :libsurfaceflinger_unittest && adb sync; adb shell \
+    /data/nativetest/libsurfaceflinger_unittest/libsurfaceflinger_unittest \
+    --gtest_filter="LayerSnapshotTest.*" --gtest_brief=1
+*/
+
+class LayerSnapshotTest : public LayerHierarchyTestBase {
+protected:
+    LayerSnapshotTest() : LayerHierarchyTestBase() {
+        UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    }
+
+    void createRootLayer(uint32_t id) override {
+        LayerHierarchyTestBase::createRootLayer(id);
+        setColor(id);
+    }
+
+    void createLayer(uint32_t id, uint32_t parentId) override {
+        LayerHierarchyTestBase::createLayer(id, parentId);
+        setColor(parentId);
+    }
+
+    void mirrorLayer(uint32_t id, uint32_t parent, uint32_t layerToMirror) override {
+        LayerHierarchyTestBase::mirrorLayer(id, parent, layerToMirror);
+        setColor(id);
+    }
+
+    void updateAndVerify(LayerSnapshotBuilder& actualBuilder, bool hasDisplayChanges,
+                         const std::vector<uint32_t> expectedVisibleLayerIdsInZOrder) {
+        if (mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)) {
+            mHierarchyBuilder.update(mLifecycleManager.getLayers(),
+                                     mLifecycleManager.getDestroyedLayers());
+        }
+        LayerSnapshotBuilder::Args args{
+                .root = mHierarchyBuilder.getHierarchy(),
+                .layerLifecycleManager = mLifecycleManager,
+                .includeMetadata = false,
+                .displays = mFrontEndDisplayInfos,
+                .displayChanges = hasDisplayChanges,
+                .globalShadowSettings = globalShadowSettings,
+        };
+        actualBuilder.update(args);
+
+        // rebuild layer snapshots from scratch and verify that it matches the updated state.
+        LayerSnapshotBuilder expectedBuilder(args);
+        mLifecycleManager.commitChanges();
+        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);
+        }
+        EXPECT_EQ(expectedVisibleLayerIdsInZOrder, actualVisibleLayerIdsInZOrder);
+    }
+
+    LayerSnapshot* getSnapshot(uint32_t layerId) { return mSnapshotBuilder.getSnapshot(layerId); }
+
+    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;
+};
+const std::vector<uint32_t> LayerSnapshotTest::STARTING_ZORDER = {1,   11,   111, 12, 121,
+                                                                  122, 1221, 13,  2};
+
+TEST_F(LayerSnapshotTest, buildSnapshot) {
+    LayerSnapshotBuilder::Args args{
+            .root = mHierarchyBuilder.getHierarchy(),
+            .layerLifecycleManager = mLifecycleManager,
+            .includeMetadata = false,
+            .displays = mFrontEndDisplayInfos,
+            .globalShadowSettings = globalShadowSettings,
+    };
+    LayerSnapshotBuilder builder(args);
+}
+
+TEST_F(LayerSnapshotTest, updateSnapshot) {
+    LayerSnapshotBuilder::Args args{
+            .root = mHierarchyBuilder.getHierarchy(),
+            .layerLifecycleManager = mLifecycleManager,
+            .includeMetadata = false,
+            .displays = mFrontEndDisplayInfos,
+            .globalShadowSettings = globalShadowSettings,
+    };
+
+    LayerSnapshotBuilder builder;
+    builder.update(args);
+}
+
+// update using parent snapshot data
+TEST_F(LayerSnapshotTest, croppedByParent) {
+    /// MAKE ALL LAYERS VISIBLE BY DEFAULT
+    DisplayInfo info;
+    info.info.logicalHeight = 100;
+    info.info.logicalWidth = 200;
+    mFrontEndDisplayInfos.emplace_or_replace(ui::LayerStack::fromValue(1), info);
+    Rect layerCrop(0, 0, 10, 20);
+    setCrop(11, layerCrop);
+    EXPECT_TRUE(mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Geometry));
+    UPDATE_AND_VERIFY_WITH_DISPLAY_CHANGES(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_EQ(getSnapshot(11)->geomCrop, layerCrop);
+    EXPECT_EQ(getSnapshot(111)->geomLayerBounds, layerCrop.toFloatRect());
+    float maxHeight = static_cast<float>(info.info.logicalHeight * 10);
+    float maxWidth = static_cast<float>(info.info.logicalWidth * 10);
+
+    FloatRect maxDisplaySize(-maxWidth, -maxHeight, maxWidth, maxHeight);
+    EXPECT_EQ(getSnapshot(1)->geomLayerBounds, maxDisplaySize);
+}
+
+// visibility tests
+TEST_F(LayerSnapshotTest, newLayerHiddenByPolicy) {
+    createLayer(112, 11);
+    hideLayer(112);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+    showLayer(112);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 11, 111, 112, 12, 121, 122, 1221, 13, 2});
+}
+
+TEST_F(LayerSnapshotTest, hiddenByParent) {
+    hideLayer(11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 121, 122, 1221, 13, 2});
+}
+
+TEST_F(LayerSnapshotTest, reparentShowsChild) {
+    hideLayer(11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 121, 122, 1221, 13, 2});
+
+    showLayer(11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+}
+
+TEST_F(LayerSnapshotTest, reparentHidesChild) {
+    hideLayer(11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 121, 122, 1221, 13, 2});
+
+    reparentLayer(121, 11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 122, 1221, 13, 2});
+}
+
+TEST_F(LayerSnapshotTest, unHidingUpdatesSnapshot) {
+    hideLayer(11);
+    Rect crop(1, 2, 3, 4);
+    setCrop(111, crop);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 121, 122, 1221, 13, 2});
+
+    showLayer(11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_EQ(getSnapshot(111)->geomLayerBounds, crop.toFloatRect());
+}
+
+TEST_F(LayerSnapshotTest, childBehindParentCanBeHiddenByParent) {
+    setZ(111, -1);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 111, 11, 12, 121, 122, 1221, 13, 2});
+
+    hideLayer(11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 121, 122, 1221, 13, 2});
+}
+
+// relative tests
+TEST_F(LayerSnapshotTest, RelativeParentCanHideChild) {
+    reparentRelativeLayer(13, 11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 11, 13, 111, 12, 121, 122, 1221, 2});
+
+    hideLayer(11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 121, 122, 1221, 2});
+}
+
+TEST_F(LayerSnapshotTest, ReparentingToHiddenRelativeParentHidesChild) {
+    hideLayer(11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 121, 122, 1221, 13, 2});
+    reparentRelativeLayer(13, 11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 12, 121, 122, 1221, 2});
+}
+
+TEST_F(LayerSnapshotTest, AlphaInheritedByChildren) {
+    setAlpha(1, 0.5);
+    setAlpha(122, 0.5);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_EQ(getSnapshot(12)->alpha, 0.5f);
+    EXPECT_EQ(getSnapshot(1221)->alpha, 0.25f);
+}
+
+// Change states
+TEST_F(LayerSnapshotTest, UpdateClearsPreviousChangeStates) {
+    setCrop(1, Rect(1, 2, 3, 4));
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_TRUE(getSnapshot(1)->changes.get() != 0);
+    EXPECT_TRUE(getSnapshot(11)->changes.get() != 0);
+    setCrop(2, Rect(1, 2, 3, 4));
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_TRUE(getSnapshot(2)->changes.get() != 0);
+    EXPECT_TRUE(getSnapshot(1)->changes.get() == 0);
+    EXPECT_TRUE(getSnapshot(11)->changes.get() == 0);
+}
+
+TEST_F(LayerSnapshotTest, FastPathClearsPreviousChangeStates) {
+    setColor(11, {1._hf, 0._hf, 0._hf});
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_TRUE(getSnapshot(11)->changes.get() != 0);
+    EXPECT_TRUE(getSnapshot(1)->changes.get() == 0);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_TRUE(getSnapshot(11)->changes.get() == 0);
+}
+
+TEST_F(LayerSnapshotTest, FastPathSetsChangeFlagToContent) {
+    setColor(1, {1._hf, 0._hf, 0._hf});
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+    EXPECT_EQ(getSnapshot(1)->changes, RequestedLayerState::Changes::Content);
+}
+
+} // namespace android::surfaceflinger::frontend