SF: More frontend fixes

- Crop mirrored layers with the mirror root. Previously we were
 cropping the layers with the original layer and not the clone.
- Explicitly make unreachable nodes invisible. Fixes an issue where
we accessed stale snapshots that were no longer reachable.
- Update buffer geometry (inverseTransformDisplay) when display state
changes.
- Blur fixes.

Test: presubmit
Bug: 238781169

Change-Id: I6f88f2456c3fd15c9d819ec2272aee639badcd19
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index a4fac1c..afe557e 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -19,6 +19,7 @@
 #define LOG_TAG "LayerHierarchy"
 
 #include "LayerHierarchy.h"
+#include "LayerLog.h"
 #include "SwapErase.h"
 
 namespace android::surfaceflinger::frontend {
@@ -259,6 +260,7 @@
 }
 
 void LayerHierarchyBuilder::onLayerDestroyed(RequestedLayerState* layer) {
+    LLOGV(layer->id, "");
     LayerHierarchy* hierarchy = getHierarchyFromId(layer->id, /*crashOnFailure=*/false);
     if (!hierarchy) {
         // Layer was never part of the hierarchy if it was created and destroyed in the same
@@ -408,29 +410,32 @@
     if (id == UNASSIGNED_LAYER_ID) {
         return "TraversalPath{ROOT}";
     }
-    std::string debugString = "TraversalPath{.id = " + std::to_string(id);
+    std::stringstream ss;
+    ss << "TraversalPath{.id = " << id;
 
-    if (!mirrorRootIds.empty()) {
-        debugString += ", .mirrorRootIds=";
-        for (auto rootId : mirrorRootIds) {
-            debugString += std::to_string(rootId) + ",";
-        }
+    if (mirrorRootId != UNASSIGNED_LAYER_ID) {
+        ss << ", .mirrorRootId=" << mirrorRootId;
     }
 
     if (!relativeRootIds.empty()) {
-        debugString += ", .relativeRootIds=";
+        ss << ", .relativeRootIds=";
         for (auto rootId : relativeRootIds) {
-            debugString += std::to_string(rootId) + ",";
+            ss << rootId << ",";
         }
     }
 
     if (hasRelZLoop()) {
-        debugString += ", hasRelZLoop=true invalidRelativeRootId=";
-        debugString += std::to_string(invalidRelativeRootId) + ",";
+        ss << "hasRelZLoop=true invalidRelativeRootId=" << invalidRelativeRootId << ",";
     }
+    ss << "}";
+    return ss.str();
+}
 
-    debugString += "}";
-    return debugString;
+LayerHierarchy::TraversalPath LayerHierarchy::TraversalPath::getMirrorRoot() const {
+    LOG_ALWAYS_FATAL_IF(!isClone(), "Cannot get mirror root of a non cloned node");
+    TraversalPath mirrorRootPath = *this;
+    mirrorRootPath.id = mirrorRootId;
+    return mirrorRootPath;
 }
 
 // Helper class to update a passed in TraversalPath when visiting a child. When the object goes out
@@ -438,16 +443,13 @@
 LayerHierarchy::ScopedAddToTraversalPath::ScopedAddToTraversalPath(TraversalPath& traversalPath,
                                                                    uint32_t layerId,
                                                                    LayerHierarchy::Variant variant)
-      : mTraversalPath(traversalPath),
-        mParentId(traversalPath.id),
-        mParentVariant(traversalPath.variant),
-        mParentDetached(traversalPath.detached) {
+      : mTraversalPath(traversalPath), mParentPath(traversalPath) {
     // Update the traversal id with the child layer id and variant. Parent id and variant are
     // stored to reset the id upon destruction.
     traversalPath.id = layerId;
     traversalPath.variant = variant;
     if (variant == LayerHierarchy::Variant::Mirror) {
-        traversalPath.mirrorRootIds.emplace_back(layerId);
+        traversalPath.mirrorRootId = layerId;
     } else if (variant == LayerHierarchy::Variant::Relative) {
         if (std::find(traversalPath.relativeRootIds.begin(), traversalPath.relativeRootIds.end(),
                       layerId) != traversalPath.relativeRootIds.end()) {
@@ -462,16 +464,16 @@
     // Reset the traversal id to its original parent state using the state that was saved in
     // the constructor.
     if (mTraversalPath.variant == LayerHierarchy::Variant::Mirror) {
-        mTraversalPath.mirrorRootIds.pop_back();
+        mTraversalPath.mirrorRootId = mParentPath.mirrorRootId;
     } else if (mTraversalPath.variant == LayerHierarchy::Variant::Relative) {
         mTraversalPath.relativeRootIds.pop_back();
     }
     if (mTraversalPath.invalidRelativeRootId == mTraversalPath.id) {
         mTraversalPath.invalidRelativeRootId = UNASSIGNED_LAYER_ID;
     }
-    mTraversalPath.id = mParentId;
-    mTraversalPath.variant = mParentVariant;
-    mTraversalPath.detached = mParentDetached;
+    mTraversalPath.id = mParentPath.id;
+    mTraversalPath.variant = mParentPath.variant;
+    mTraversalPath.detached = mParentPath.detached;
 }
 
 } // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index ca8d301..2ab897b 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -50,12 +50,32 @@
         ftl_last = Mirror,
     };
     // Represents a unique path to a node.
+    // The layer hierarchy is represented as a graph. Each node can be visited by multiple parents.
+    // This allows us to represent mirroring in an efficient way. See the example below:
+    // root
+    // ├─ A {Traversal path id = 1}
+    // ├─ B {Traversal path id = 2}
+    // │  ├─ C {Traversal path id = 3}
+    // │  ├─ D {Traversal path id = 4}
+    // │  └─ E {Traversal path id = 5}
+    // ├─ F (Mirrors B) {Traversal path id = 6}
+    // └─ G (Mirrors F) {Traversal path id = 7}
+    //
+    // C, D and E can be traversed via B or via F then B or via G then F then B.
+    // Depending on how the node is reached, its properties such as geometry or visibility might be
+    // different. And we can uniquely identify the node by keeping track of the nodes leading up to
+    // it. But to be more efficient we only need to track the nodes id and the top mirror root path.
+    // So C for example, would have the following unique traversal paths:
+    //  - {Traversal path id = 3}
+    //  - {Traversal path id = 3, mirrorRootId = 6}
+    //  - {Traversal path id = 3, mirrorRootId = 7}
+
     struct TraversalPath {
         uint32_t id;
         LayerHierarchy::Variant variant;
         // Mirrored layers can have a different geometry than their parents so we need to track
         // the mirror roots in the traversal.
-        ftl::SmallVector<uint32_t, 5> mirrorRootIds;
+        uint32_t mirrorRootId = UNASSIGNED_LAYER_ID;
         // Relative layers can be visited twice, once by their parent and then once again by
         // their relative parent. We keep track of the roots here to detect any loops in the
         // hierarchy. If a relative root already exists in the list while building the
@@ -73,10 +93,11 @@
         // Returns true if the node or its parents are not Detached.
         bool isAttached() const { return !detached; }
         // Returns true if the node is a clone.
-        bool isClone() const { return !mirrorRootIds.empty(); }
+        bool isClone() const { return mirrorRootId != UNASSIGNED_LAYER_ID; }
+        TraversalPath getMirrorRoot() const;
 
         bool operator==(const TraversalPath& other) const {
-            return id == other.id && mirrorRootIds == other.mirrorRootIds;
+            return id == other.id && mirrorRootId == other.mirrorRootId;
         }
         std::string toString() const;
 
@@ -93,9 +114,7 @@
 
     private:
         TraversalPath& mTraversalPath;
-        uint32_t mParentId;
-        LayerHierarchy::Variant mParentVariant;
-        bool mParentDetached;
+        TraversalPath mParentPath;
     };
     LayerHierarchy(RequestedLayerState* layer);
 
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index 547a852..66197be 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -22,6 +22,7 @@
 #include "LayerLifecycleManager.h"
 #include "Layer.h" // temporarily needed for LayerHandle
 #include "LayerHandle.h"
+#include "LayerLog.h"
 #include "SwapErase.h"
 
 namespace android::surfaceflinger::frontend {
@@ -36,6 +37,7 @@
     mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
     for (auto& newLayer : newLayers) {
         RequestedLayerState& layer = *newLayer.get();
+        LLOGV(layer.id, "%s layer %s", __func__, layer.getDebugStringShort().c_str());
         auto [it, inserted] = mIdToLayer.try_emplace(layer.id, References{.owner = layer});
         if (!inserted) {
             LOG_ALWAYS_FATAL("Duplicate layer id %d found. Existing layer: %s", layer.id,
@@ -146,7 +148,7 @@
     while (it != mLayers.end()) {
         RequestedLayerState* layer = it->get();
         if (layer->changes.test(RequestedLayerState::Changes::Destroyed)) {
-            ALOGV("%s destroyed layer %s", __func__, layer->getDebugStringShort().c_str());
+            LLOGV(layer->id, "destroyed layer %s", layer->getDebugStringShort().c_str());
             std::iter_swap(it, mLayers.end() - 1);
             mDestroyedLayers.emplace_back(std::move(mLayers.back()));
             if (it == mLayers.end() - 1) {
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 3ed24b2..c9aeb24 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -259,8 +259,8 @@
     }
 }
 
-void updateVisibility(LayerSnapshot& snapshot) {
-    snapshot.isVisible = snapshot.getIsVisible();
+void updateVisibility(LayerSnapshot& snapshot, bool visible) {
+    snapshot.isVisible = visible;
 
     // TODO(b/238781169) we are ignoring this compat for now, since we will have
     // to remove any optimization based on visibility.
@@ -273,9 +273,9 @@
     // We are just using these layers for occlusion detection in
     // InputDispatcher, and obviously if they aren't visible they can't occlude
     // anything.
-    const bool visible =
+    const bool visibleForInput =
             (snapshot.inputInfo.token != nullptr) ? snapshot.canReceiveInput() : snapshot.isVisible;
-    snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visible);
+    snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
 }
 
 bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
@@ -521,7 +521,7 @@
                 }
 
                 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
-                    updateVisibility(*snapshot);
+                    updateVisibility(*snapshot, snapshot->getIsVisible());
                     size_t oldZ = snapshot->globalZ;
                     size_t newZ = globalZ++;
                     snapshot->globalZ = newZ;
@@ -539,7 +539,8 @@
     mNumInterestingSnapshots = (int)globalZ;
     while (globalZ < mSnapshots.size()) {
         mSnapshots[globalZ]->globalZ = globalZ;
-        updateVisibility(*mSnapshots[globalZ]);
+        /* mark unreachable snapshots as explicitly invisible */
+        updateVisibility(*mSnapshots[globalZ], false);
         globalZ++;
     }
 }
@@ -634,11 +635,15 @@
     const bool forceUpdate = newSnapshot || args.forceUpdate ||
             snapshot.changes.any(RequestedLayerState::Changes::Visibility |
                                  RequestedLayerState::Changes::Created);
+    snapshot.outputFilter.layerStack = requested.parentId != UNASSIGNED_LAYER_ID
+            ? parentSnapshot.outputFilter.layerStack
+            : requested.layerStack;
+
     uint32_t displayRotationFlags =
             getDisplayRotationFlags(args.displays, snapshot.outputFilter.layerStack);
 
     // always update the buffer regardless of visibility
-    if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES) {
+    if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) {
         snapshot.acquireFence =
                 (requested.externalTexture &&
                  requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged))
@@ -727,9 +732,13 @@
     if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content)) {
         snapshot.color.rgb = requested.getColor().rgb;
         snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
-        snapshot.backgroundBlurRadius =
-                args.supportsBlur ? static_cast<int>(requested.backgroundBlurRadius) : 0;
+        snapshot.backgroundBlurRadius = args.supportsBlur
+                ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
+                : 0;
         snapshot.blurRegions = requested.blurRegions;
+        for (auto& region : snapshot.blurRegions) {
+            region.alpha = region.alpha * snapshot.color.a;
+        }
         snapshot.hdrMetadata = requested.hdrMetadata;
     }
 
@@ -965,7 +974,7 @@
     // touches from going outside the cloned area.
     if (path.isClone()) {
         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
-        auto clonedRootSnapshot = getSnapshot(path.mirrorRootIds.back());
+        auto clonedRootSnapshot = getSnapshot(path.getMirrorRoot());
         if (clonedRootSnapshot) {
             const Rect rect =
                     displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index f4544fd..0902ab8 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -115,8 +115,8 @@
     struct TraversalPathHash {
         std::size_t operator()(const LayerHierarchy::TraversalPath& key) const {
             uint32_t hashCode = key.id * 31;
-            for (auto mirrorRoot : key.mirrorRootIds) {
-                hashCode += mirrorRoot * 31;
+            if (key.mirrorRootId != UNASSIGNED_LAYER_ID) {
+                hashCode += key.mirrorRootId * 31;
             }
             return std::hash<size_t>{}(hashCode);
         }
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index d63b126..2834084 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -144,7 +144,7 @@
     const half oldAlpha = color.a;
     const bool hadBufferOrSideStream = hasValidBuffer() || sidebandStream != nullptr;
     const layer_state_t& clientState = resolvedComposerState.state;
-
+    const bool hadBlur = hasBlur();
     uint64_t clientChanges = what | layer_state_t::diff(clientState);
     layer_state_t::merge(clientState);
     what = clientChanges;
@@ -174,6 +174,12 @@
                     RequestedLayerState::Changes::VisibleRegion;
         }
     }
+    if (what & (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged)) {
+        if (hadBlur != hasBlur()) {
+            changes |= RequestedLayerState::Changes::Visibility |
+                    RequestedLayerState::Changes::VisibleRegion;
+        }
+    }
     if (clientChanges & layer_state_t::HIERARCHY_CHANGES)
         changes |= RequestedLayerState::Changes::Hierarchy;
     if (clientChanges & layer_state_t::CONTENT_CHANGES)
@@ -319,11 +325,11 @@
 }
 
 std::string RequestedLayerState::getDebugString() const {
-    return "[" + std::to_string(id) + "]" + name + ",parent=" + layerIdToString(parentId) +
-            ",relativeParent=" + layerIdToString(relativeParentId) +
-            ",isRelativeOf=" + std::to_string(isRelativeOf) +
-            ",mirrorIds=" + layerIdsToString(mirrorIds) +
-            ",handleAlive=" + std::to_string(handleAlive) + ",z=" + std::to_string(z);
+    std::stringstream debug;
+    debug << "RequestedLayerState{" << name << " parent=" << layerIdToString(parentId)
+          << " relativeParent=" << layerIdToString(relativeParentId)
+          << " mirrorId=" << layerIdsToString(mirrorIds) << " handle=" << handleAlive << " z=" << z;
+    return debug.str();
 }
 
 std::string RequestedLayerState::getDebugStringShort() const {
@@ -442,4 +448,8 @@
             windowInfo->inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
 }
 
+bool RequestedLayerState::hasBlur() const {
+    return backgroundBlurRadius > 0 || blurRegions.size() > 0;
+}
+
 } // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 6317b95..6840b25 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -71,6 +71,7 @@
     aidl::android::hardware::graphics::composer3::Composition getCompositionType() const;
     bool hasValidRelativeParent() const;
     bool hasInputInfo() const;
+    bool hasBlur() const;
 
     // Layer serial number.  This gives layers an explicit ordering, so we
     // have a stable sort order when their layer stack and Z-order are