[sf] destroy unreachable snapshots

Keep track of unreachable snapshots and destroy
them. This is a more robust way of cleaning up
snapshots rather than going through destroyed
layer handles. This way we will handle mirrored
snapshots when the original layer gets destroyed.

Test: presubmit
Bug: 238781169
Change-Id: Iddd5754ae71086719711ecaab218fc5f52e11ef5
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index 9757640..07aa122 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -85,6 +85,7 @@
     ui::Transform::RotationFlags fixedTransformHint;
     bool handleSkipScreenshotFlag = false;
     LayerHierarchy::TraversalPath mirrorRootPath;
+    bool unreachable = true;
     ChildState childState;
 
     static bool isOpaqueFormat(PixelFormat format);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 9ccf6dc..db6e716 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -435,22 +435,18 @@
         }
     }
 
-    sortSnapshotsByZ(args);
+    const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
     clearChanges(mRootSnapshot);
 
     // Destroy unreachable snapshots
-    if (args.layerLifecycleManager.getDestroyedLayers().empty()) {
+    if (!hasUnreachableSnapshots) {
         return;
     }
 
-    std::unordered_set<uint32_t> destroyedLayerIds;
-    for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
-        destroyedLayerIds.emplace(destroyedLayer->id);
-    }
     auto it = mSnapshots.begin();
     while (it < mSnapshots.end()) {
         auto& traversalPath = it->get()->path;
-        if (destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) {
+        if (!it->get()->unreachable) {
             it++;
             continue;
         }
@@ -534,18 +530,21 @@
     return snapshot;
 }
 
-void LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
+bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
     if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
         !args.layerLifecycleManager.getGlobalChanges().any(
                 RequestedLayerState::Changes::Hierarchy |
                 RequestedLayerState::Changes::Visibility)) {
         // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
         // the snapshots.
-        return;
+        return false;
     }
-
     mResortSnapshots = false;
 
+    for (auto& snapshot : mSnapshots) {
+        snapshot->unreachable = true;
+    }
+
     size_t globalZ = 0;
     args.root.traverseInZOrder(
             [this, &globalZ](const LayerHierarchy&,
@@ -555,11 +554,7 @@
                     return false;
                 }
 
-                if (snapshot->isHiddenByPolicy() &&
-                    !snapshot->changes.test(RequestedLayerState::Changes::Visibility)) {
-                    return false;
-                }
-
+                snapshot->unreachable = false;
                 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
                     updateVisibility(*snapshot, snapshot->getIsVisible());
                     size_t oldZ = snapshot->globalZ;
@@ -577,12 +572,17 @@
                 return true;
             });
     mNumInterestingSnapshots = (int)globalZ;
+    bool hasUnreachableSnapshots = false;
     while (globalZ < mSnapshots.size()) {
         mSnapshots[globalZ]->globalZ = globalZ;
         /* mark unreachable snapshots as explicitly invisible */
         updateVisibility(*mSnapshots[globalZ], false);
+        if (mSnapshots[globalZ]->unreachable) {
+            hasUnreachableSnapshots = true;
+        }
         globalZ++;
     }
+    return hasUnreachableSnapshots;
 }
 
 void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index 07b0d14..3997a0a 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -112,7 +112,8 @@
     void updateInput(LayerSnapshot& snapshot, const RequestedLayerState& requested,
                      const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath& path,
                      const Args& args);
-    void sortSnapshotsByZ(const Args& args);
+    // Return true if there are unreachable snapshots
+    bool sortSnapshotsByZ(const Args& args);
     LayerSnapshot* createSnapshot(const LayerHierarchy::TraversalPath& id,
                                   const RequestedLayerState& layer,
                                   const LayerSnapshot& parentSnapshot);
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
index 1916404..77dc868 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
@@ -263,6 +263,37 @@
     EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
 }
 
+TEST_F(LayerHierarchyTest, reparentRelativeLayer) {
+    LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
+    reparentRelativeLayer(11, 2);
+    UPDATE_AND_VERIFY(hierarchyBuilder);
+
+    std::vector<uint32_t> expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 11, 111};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    expectedTraversalPath = {1, 12, 121, 122, 1221, 13, 2, 11, 111};
+    EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    expectedTraversalPath = {};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+
+    reparentLayer(11, 1);
+    UPDATE_AND_VERIFY(hierarchyBuilder);
+    expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 11, 111};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    expectedTraversalPath = {1, 12, 121, 122, 1221, 13, 2, 11, 111};
+    EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    expectedTraversalPath = {};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+
+    setZ(11, 0);
+    UPDATE_AND_VERIFY(hierarchyBuilder);
+    expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2};
+    EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+    expectedTraversalPath = {};
+    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+}
+
 // mirror tests
 TEST_F(LayerHierarchyTest, canTraverseMirrorLayer) {
     LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 14569ab..db0b907 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -391,4 +391,39 @@
     UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
 }
 
+TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterMirroring) {
+    size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
+    createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
+    setLayerStack(3, 1);
+    std::vector<uint32_t> expected = {3, 1,  11,  111, 12,  121, 122,  1221, 13, 2,
+                                      1, 11, 111, 12,  121, 122, 1221, 13,   2};
+    UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+    destroyLayerHandle(3);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+    EXPECT_EQ(startingNumSnapshots, mSnapshotBuilder.getSnapshots().size());
+}
+
+// Rel z doesn't create duplicate snapshots but this is for completeness
+TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterRelZ) {
+    size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
+    reparentRelativeLayer(13, 11);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 11, 13, 111, 12, 121, 122, 1221, 2});
+    setZ(13, 0);
+    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+    EXPECT_EQ(startingNumSnapshots, mSnapshotBuilder.getSnapshots().size());
+}
+
+TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterLayerDestruction) {
+    size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
+    destroyLayerHandle(2);
+    destroyLayerHandle(122);
+
+    std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13};
+    UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+
+    EXPECT_LE(startingNumSnapshots - 2, mSnapshotBuilder.getSnapshots().size());
+}
+
 } // namespace android::surfaceflinger::frontend