SF: Introduce LayerLifecycleManager

LayerLifecycleManager keeps track of layer lifecyle and state
changes. This breaks the existing model of using refbase and
LayerHandles to keep layer's alive. Instead, the
LayerLifecycleManager owns each layer and destroys them based
on the layer parent state and its handle state.

In addition, this class keeps track of requested layer state
changes, keeping track of change flags that make the data easier
to consume down the pipeline.

The code is not enabled.

Bug: 238781169
Test: presubmit

Change-Id: I4e77efd0e689ddb513beb947d31c2fb1cd33880c
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index ac74c8a..b01a3db 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -272,6 +272,7 @@
     WindowInfoHandle(const WindowInfo& other);
 
     inline const WindowInfo* getInfo() const { return &mInfo; }
+    inline WindowInfo* editInfo() { return &mInfo; }
 
     sp<IBinder> getToken() const;
 
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 14fdd12..b1bd705 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -157,6 +157,8 @@
         "EventLog/EventLog.cpp",
         "FrontEnd/LayerCreationArgs.cpp",
         "FrontEnd/LayerHandle.cpp",
+        "FrontEnd/LayerLifecycleManager.cpp",
+        "FrontEnd/RequestedLayerState.cpp",
         "FrontEnd/TransactionHandler.cpp",
         "FlagManager.cpp",
         "FpsReporter.cpp",
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
new file mode 100644
index 0000000..1108246
--- /dev/null
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#undef LOG_TAG
+#define LOG_TAG "LayerLifecycleManager"
+
+#include "LayerLifecycleManager.h"
+#include "Layer.h" // temporarily needed for LayerHandle
+#include "LayerHandle.h"
+#include "SwapErase.h"
+
+namespace android::surfaceflinger::frontend {
+
+using namespace ftl::flag_operators;
+
+void LayerLifecycleManager::addLayers(std::vector<std::unique_ptr<RequestedLayerState>> newLayers) {
+    if (newLayers.empty()) {
+        return;
+    }
+
+    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
+    for (auto& newLayer : newLayers) {
+        RequestedLayerState& layer = *newLayer.get();
+        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,
+                             it->second.owner.getDebugString().c_str());
+        }
+
+        linkLayer(layer.parentId, layer.id);
+        linkLayer(layer.relativeParentId, layer.id);
+        linkLayer(layer.mirrorId, layer.id);
+        linkLayer(layer.touchCropId, layer.id);
+
+        mLayers.emplace_back(std::move(newLayer));
+    }
+}
+
+void LayerLifecycleManager::onHandlesDestroyed(const std::vector<uint32_t>& destroyedHandles) {
+    std::vector<uint32_t> layersToBeDestroyed;
+    for (const auto& layerId : destroyedHandles) {
+        auto it = mIdToLayer.find(layerId);
+        if (it == mIdToLayer.end()) {
+            LOG_ALWAYS_FATAL("%s Layerid not found %d", __func__, layerId);
+            continue;
+        }
+        RequestedLayerState& layer = it->second.owner;
+        layer.handleAlive = false;
+        if (!layer.canBeDestroyed()) {
+            continue;
+        }
+        layer.changes |= RequestedLayerState::Changes::Destroyed;
+        layersToBeDestroyed.emplace_back(layerId);
+    }
+
+    if (layersToBeDestroyed.empty()) {
+        return;
+    }
+
+    mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
+    for (size_t i = 0; i < layersToBeDestroyed.size(); i++) {
+        uint32_t layerId = layersToBeDestroyed[i];
+        auto it = mIdToLayer.find(layerId);
+        if (it == mIdToLayer.end()) {
+            LOG_ALWAYS_FATAL("%s Layer with id %d not found", __func__, layerId);
+            continue;
+        }
+
+        RequestedLayerState& layer = it->second.owner;
+
+        unlinkLayer(layer.parentId, layer.id);
+        unlinkLayer(layer.relativeParentId, layer.id);
+        unlinkLayer(layer.mirrorId, layer.id);
+        unlinkLayer(layer.touchCropId, layer.id);
+
+        auto& references = it->second.references;
+        for (uint32_t linkedLayerId : references) {
+            RequestedLayerState* linkedLayer = getLayerFromId(linkedLayerId);
+            if (!linkedLayer) {
+                LOG_ALWAYS_FATAL("%s Layerid reference %d not found for %d", __func__,
+                                 linkedLayerId, layer.id);
+                continue;
+            };
+            if (linkedLayer->parentId == layer.id) {
+                linkedLayer->parentId = UNASSIGNED_LAYER_ID;
+                if (linkedLayer->canBeDestroyed()) {
+                    linkedLayer->changes |= RequestedLayerState::Changes::Destroyed;
+                    layersToBeDestroyed.emplace_back(linkedLayer->id);
+                }
+            }
+            if (linkedLayer->relativeParentId == layer.id) {
+                linkedLayer->relativeParentId = UNASSIGNED_LAYER_ID;
+            }
+            if (linkedLayer->mirrorId == layer.id) {
+                linkedLayer->mirrorId = UNASSIGNED_LAYER_ID;
+            }
+            if (linkedLayer->touchCropId == layer.id) {
+                linkedLayer->touchCropId = UNASSIGNED_LAYER_ID;
+            }
+        }
+        mIdToLayer.erase(it);
+    }
+
+    auto it = mLayers.begin();
+    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());
+            std::iter_swap(it, mLayers.end() - 1);
+            mDestroyedLayers.emplace_back(std::move(mLayers.back()));
+            mLayers.erase(mLayers.end() - 1);
+        } else {
+            it++;
+        }
+    }
+}
+
+void LayerLifecycleManager::applyTransactions(const std::vector<TransactionState>& transactions) {
+    for (const auto& transaction : transactions) {
+        for (const auto& resolvedComposerState : transaction.states) {
+            const auto& clientState = resolvedComposerState.state;
+            uint32_t layerId = LayerHandle::getLayerId(clientState.surface);
+            if (layerId == UNASSIGNED_LAYER_ID) {
+                ALOGW("%s Handle %p is not valid", __func__, clientState.surface.get());
+                continue;
+            }
+
+            RequestedLayerState* layer = getLayerFromId(layerId);
+            if (layer == nullptr) {
+                LOG_ALWAYS_FATAL("%s Layer with handle %p (layerid=%d) not found", __func__,
+                                 clientState.surface.get(), layerId);
+                continue;
+            }
+
+            if (!layer->handleAlive) {
+                LOG_ALWAYS_FATAL("%s Layer's handle %p (layerid=%d) is not alive. Possible out of "
+                                 "order LayerLifecycleManager updates",
+                                 __func__, clientState.surface.get(), layerId);
+                continue;
+            }
+
+            uint32_t oldParentId = layer->parentId;
+            uint32_t oldRelativeParentId = layer->relativeParentId;
+            uint32_t oldTouchCropId = layer->touchCropId;
+            layer->merge(resolvedComposerState);
+
+            if (layer->what & layer_state_t::eBackgroundColorChanged) {
+                if (layer->bgColorLayerId == UNASSIGNED_LAYER_ID && layer->bgColorAlpha != 0) {
+                    LayerCreationArgs backgroundLayerArgs{nullptr,
+                                                          nullptr,
+                                                          layer->name + "BackgroundColorLayer",
+                                                          ISurfaceComposerClient::eFXSurfaceEffect,
+                                                          {}};
+                    std::vector<std::unique_ptr<RequestedLayerState>> newLayers;
+                    newLayers.emplace_back(
+                            std::make_unique<RequestedLayerState>(backgroundLayerArgs));
+                    RequestedLayerState* backgroundLayer = newLayers.back().get();
+                    backgroundLayer->handleAlive = false;
+                    backgroundLayer->parentId = layer->id;
+                    backgroundLayer->z = std::numeric_limits<int32_t>::min();
+                    backgroundLayer->color.rgb = layer->color.rgb;
+                    backgroundLayer->color.a = layer->bgColorAlpha;
+                    backgroundLayer->dataspace = layer->bgColorDataspace;
+
+                    layer->bgColorLayerId = backgroundLayer->id;
+                    addLayers({std::move(newLayers)});
+                } else if (layer->bgColorLayerId != UNASSIGNED_LAYER_ID &&
+                           layer->bgColorAlpha == 0) {
+                    RequestedLayerState* bgColorLayer = getLayerFromId(layer->bgColorLayerId);
+                    bgColorLayer->parentId = UNASSIGNED_LAYER_ID;
+                    onHandlesDestroyed({layer->bgColorLayerId});
+                } else if (layer->bgColorLayerId != UNASSIGNED_LAYER_ID) {
+                    RequestedLayerState* bgColorLayer = getLayerFromId(layer->bgColorLayerId);
+                    bgColorLayer->color.rgb = layer->color.rgb;
+                    bgColorLayer->color.a = layer->bgColorAlpha;
+                    bgColorLayer->dataspace = layer->bgColorDataspace;
+                    mGlobalChanges |= RequestedLayerState::Changes::Content;
+                }
+            }
+
+            if (oldParentId != layer->parentId) {
+                unlinkLayer(oldParentId, layer->id);
+                linkLayer(layer->parentId, layer->id);
+            }
+            if (oldRelativeParentId != layer->relativeParentId) {
+                unlinkLayer(oldRelativeParentId, layer->id);
+                linkLayer(layer->relativeParentId, layer->id);
+            }
+            if (oldTouchCropId != layer->touchCropId) {
+                unlinkLayer(oldTouchCropId, layer->id);
+                linkLayer(layer->touchCropId, layer->id);
+            }
+
+            mGlobalChanges |= layer->changes &
+                    (RequestedLayerState::Changes::Hierarchy |
+                     RequestedLayerState::Changes::Geometry |
+                     RequestedLayerState::Changes::Content);
+        }
+    }
+}
+
+void LayerLifecycleManager::commitChanges() {
+    for (auto& layer : mLayers) {
+        if (layer->changes.test(RequestedLayerState::Changes::Created)) {
+            for (auto listener : mListeners) {
+                listener->onLayerAdded(*layer);
+            }
+        }
+        layer->what = 0;
+        layer->changes.clear();
+    }
+
+    for (auto& destroyedLayer : mDestroyedLayers) {
+        if (destroyedLayer->changes.test(RequestedLayerState::Changes::Created)) {
+            for (auto listener : mListeners) {
+                listener->onLayerAdded(*destroyedLayer);
+            }
+        }
+
+        for (auto listener : mListeners) {
+            listener->onLayerDestroyed(*destroyedLayer);
+        }
+    }
+    mDestroyedLayers.clear();
+    mGlobalChanges.clear();
+}
+
+void LayerLifecycleManager::addLifecycleListener(std::shared_ptr<ILifecycleListener> listener) {
+    mListeners.emplace_back(std::move(listener));
+}
+
+void LayerLifecycleManager::removeLifecycleListener(std::shared_ptr<ILifecycleListener> listener) {
+    swapErase(mListeners, listener);
+}
+
+const std::vector<std::unique_ptr<RequestedLayerState>>& LayerLifecycleManager::getLayers() const {
+    return mLayers;
+}
+
+const std::vector<std::unique_ptr<RequestedLayerState>>& LayerLifecycleManager::getDestroyedLayers()
+        const {
+    return mDestroyedLayers;
+}
+
+const ftl::Flags<RequestedLayerState::Changes> LayerLifecycleManager::getGlobalChanges() const {
+    return mGlobalChanges;
+}
+
+RequestedLayerState* LayerLifecycleManager::getLayerFromId(uint32_t id) {
+    if (id == UNASSIGNED_LAYER_ID) {
+        return nullptr;
+    }
+    auto it = mIdToLayer.find(id);
+    if (it == mIdToLayer.end()) {
+        return nullptr;
+    }
+    return &it->second.owner;
+}
+
+std::vector<uint32_t>* LayerLifecycleManager::getLinkedLayersFromId(uint32_t id) {
+    if (id == UNASSIGNED_LAYER_ID) {
+        return nullptr;
+    }
+    auto it = mIdToLayer.find(id);
+    if (it == mIdToLayer.end()) {
+        return nullptr;
+    }
+    return &it->second.references;
+}
+
+void LayerLifecycleManager::linkLayer(uint32_t layerId, uint32_t layerToLink) {
+    if (layerToLink && layerId != UNASSIGNED_LAYER_ID) {
+        std::vector<uint32_t>* linkedLayers = getLinkedLayersFromId(layerId);
+        if (!linkedLayers) {
+            LOG_ALWAYS_FATAL("Could not find layer id %d to link %d", layerId, layerToLink);
+            return;
+        }
+        linkedLayers->emplace_back(layerToLink);
+    }
+}
+
+void LayerLifecycleManager::unlinkLayer(uint32_t& inOutLayerId, uint32_t linkedLayer) {
+    uint32_t layerId = inOutLayerId;
+    inOutLayerId = UNASSIGNED_LAYER_ID;
+
+    std::vector<uint32_t>* linkedLayers = getLinkedLayersFromId(layerId);
+    if (!linkedLayers) {
+        return;
+    }
+    swapErase(*linkedLayers, linkedLayer);
+}
+
+std::string LayerLifecycleManager::References::getDebugString() const {
+    std::string debugInfo = owner.name + "[" + std::to_string(owner.id) + "] refs:";
+    std::for_each(references.begin(), references.end(),
+                  [&debugInfo = debugInfo](const uint32_t& reference) mutable {
+                      debugInfo += std::to_string(reference) + ",";
+                  });
+    return debugInfo;
+}
+
+} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
new file mode 100644
index 0000000..ad70d3f
--- /dev/null
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "RequestedLayerState.h"
+#include "TransactionState.h"
+
+namespace android::surfaceflinger::frontend {
+
+// Owns a collection of RequestedLayerStates and manages their lifecycle
+// and state changes.
+//
+// RequestedLayerStates are tracked and destroyed if they have no parent and
+// no handle left to keep them alive. The handle does not keep a reference to
+// the RequestedLayerState but a layer id associated with the RequestedLayerState.
+// If the handle is destroyed and the RequestedLayerState does not have a parent,
+// the LayerLifecycleManager destroys the RequestedLayerState.
+//
+// Threading: This class is not thread safe, it requires external synchronization.
+//
+// Typical usage: Input states (new layers, transactions, destroyed layer handles)
+// are collected in the background passed into the LayerLifecycleManager to update
+// layer lifecycle and layer state at start of composition.
+class LayerLifecycleManager {
+public:
+    // External state changes should be updated in the following order:
+    void addLayers(std::vector<std::unique_ptr<RequestedLayerState>>);
+    void applyTransactions(const std::vector<TransactionState>&);
+    void onHandlesDestroyed(const std::vector<uint32_t>&);
+
+    // Destroys RequestedLayerStates that are marked to be destroyed. Invokes all
+    // ILifecycleListener callbacks and clears any change flags from previous state
+    // updates. This function should be called outside the hot path since it's not
+    // critical to composition.
+    void commitChanges();
+
+    class ILifecycleListener {
+    public:
+        virtual ~ILifecycleListener() = default;
+        // Called on commitChanges when a layer is added. The callback includes
+        // the layer state the client was created with as well as any state updates
+        // until changes were committed.
+        virtual void onLayerAdded(const RequestedLayerState&) = 0;
+        // Called on commitChanges when a layer has been destroyed. The callback
+        // includes the final state before the layer was destroyed.
+        virtual void onLayerDestroyed(const RequestedLayerState&) = 0;
+    };
+    void addLifecycleListener(std::shared_ptr<ILifecycleListener>);
+    void removeLifecycleListener(std::shared_ptr<ILifecycleListener>);
+    const std::vector<std::unique_ptr<RequestedLayerState>>& getLayers() const;
+    const std::vector<std::unique_ptr<RequestedLayerState>>& getDestroyedLayers() const;
+    const ftl::Flags<RequestedLayerState::Changes> getGlobalChanges() const;
+
+private:
+    friend class LayerLifecycleManagerTest;
+    friend class HierarchyBuilderTest;
+    friend class android::SurfaceFlinger;
+
+    RequestedLayerState* getLayerFromId(uint32_t);
+    std::vector<uint32_t>* getLinkedLayersFromId(uint32_t);
+    void linkLayer(uint32_t layerId, uint32_t layerToLink);
+    void unlinkLayer(uint32_t& inOutLayerId, uint32_t linkedLayer);
+
+    struct References {
+        // Lifetime tied to mLayers
+        RequestedLayerState& owner;
+        std::vector<uint32_t> references;
+        std::string getDebugString() const;
+    };
+    std::unordered_map<uint32_t, References> mIdToLayer;
+    // Listeners are invoked once changes are committed.
+    std::vector<std::shared_ptr<ILifecycleListener>> mListeners;
+
+    // Aggregation of changes since last commit.
+    ftl::Flags<RequestedLayerState::Changes> mGlobalChanges;
+    std::vector<std::unique_ptr<RequestedLayerState>> mLayers;
+    // Layers pending destruction. Layers will be destroyed once changes are committed.
+    std::vector<std::unique_ptr<RequestedLayerState>> mDestroyedLayers;
+};
+
+} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
new file mode 100644
index 0000000..45058d9
--- /dev/null
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -0,0 +1,358 @@
+/*
+ * 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 "FrontEnd/LayerCreationArgs.h"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#undef LOG_TAG
+#define LOG_TAG "RequestedLayerState"
+
+#include <private/android_filesystem_config.h>
+#include <sys/types.h>
+
+#include "Layer.h"
+#include "LayerHandle.h"
+#include "RequestedLayerState.h"
+
+namespace android::surfaceflinger::frontend {
+using ftl::Flags;
+using namespace ftl::flag_operators;
+
+namespace {
+uint32_t getLayerIdFromSurfaceControl(sp<SurfaceControl> surfaceControl) {
+    if (!surfaceControl) {
+        return UNASSIGNED_LAYER_ID;
+    }
+
+    return LayerHandle::getLayerId(surfaceControl->getHandle());
+}
+
+std::string layerIdToString(uint32_t layerId) {
+    return layerId == UNASSIGNED_LAYER_ID ? std::to_string(layerId) : "none";
+}
+
+} // namespace
+
+RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args)
+      : id(args.sequence),
+        name(args.name),
+        canBeRoot(args.addToRoot),
+        layerCreationFlags(args.flags),
+        textureName(args.textureName),
+        ownerUid(args.ownerUid),
+        ownerPid(args.ownerPid) {
+    layerId = static_cast<int32_t>(args.sequence);
+    changes |= RequestedLayerState::Changes::Created;
+    metadata.merge(args.metadata);
+    changes |= RequestedLayerState::Changes::Metadata;
+    handleAlive = true;
+    parentId = LayerHandle::getLayerId(args.parentHandle.promote());
+    mirrorId = LayerHandle::getLayerId(args.mirrorLayerHandle.promote());
+    if (mirrorId != UNASSIGNED_LAYER_ID) {
+        changes |= RequestedLayerState::Changes::Mirror;
+    }
+
+    flags = 0;
+    if (args.flags & ISurfaceComposerClient::eHidden) flags |= layer_state_t::eLayerHidden;
+    if (args.flags & ISurfaceComposerClient::eOpaque) flags |= layer_state_t::eLayerOpaque;
+    if (args.flags & ISurfaceComposerClient::eSecure) flags |= layer_state_t::eLayerSecure;
+    if (args.flags & ISurfaceComposerClient::eSkipScreenshot) {
+        flags |= layer_state_t::eLayerSkipScreenshot;
+    }
+    premultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
+    potentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
+    protectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp;
+    if (args.flags & ISurfaceComposerClient::eNoColorFill) {
+        // Set an invalid color so there is no color fill.
+        // (b/259981098) use an explicit flag instead of relying on invalid values.
+        color.r = -1.0_hf;
+        color.g = -1.0_hf;
+        color.b = -1.0_hf;
+    } else {
+        color.rgb = {0.0_hf, 0.0_hf, 0.0_hf};
+    }
+    color.a = 1.0f;
+
+    crop.makeInvalid();
+    z = 0;
+    layerStack = ui::DEFAULT_LAYER_STACK;
+    transformToDisplayInverse = false;
+    dataspace = ui::Dataspace::UNKNOWN;
+    dataspaceRequested = false;
+    hdrMetadata.validTypes = 0;
+    surfaceDamageRegion = Region::INVALID_REGION;
+    cornerRadius = 0.0f;
+    backgroundBlurRadius = 0;
+    api = -1;
+    hasColorTransform = false;
+    bufferTransform = 0;
+    requestedTransform.reset();
+    bufferData = std::make_shared<BufferData>();
+    bufferData->frameNumber = 0;
+    bufferData->acquireFence = sp<Fence>::make(-1);
+    acquireFenceTime = std::make_shared<FenceTime>(bufferData->acquireFence);
+    colorSpaceAgnostic = false;
+    frameRateSelectionPriority = Layer::PRIORITY_UNSET;
+    shadowRadius = 0.f;
+    fixedTransformHint = ui::Transform::ROT_INVALID;
+    destinationFrame.makeInvalid();
+    isTrustedOverlay = false;
+    dropInputMode = gui::DropInputMode::NONE;
+    dimmingEnabled = true;
+    defaultFrameRateCompatibility =
+            static_cast<int8_t>(scheduler::LayerInfo::FrameRateCompatibility::Default);
+    dataspace = ui::Dataspace::V0_SRGB;
+}
+
+void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerState) {
+    bool oldFlags = flags;
+    Rect oldBufferSize = getBufferSize();
+    const layer_state_t& clientState = resolvedComposerState.state;
+
+    uint64_t clientChanges = what | layer_state_t::diff(clientState);
+    layer_state_t::merge(clientState);
+    what = clientChanges;
+
+    if (clientState.what & layer_state_t::eFlagsChanged) {
+        if ((oldFlags ^ flags) & layer_state_t::eLayerHidden) {
+            changes |= RequestedLayerState::Changes::Visibility;
+        }
+        if ((oldFlags ^ flags) & layer_state_t::eIgnoreDestinationFrame) {
+            changes |= RequestedLayerState::Changes::Geometry;
+        }
+    }
+    if (clientState.what & layer_state_t::eBufferChanged && oldBufferSize != getBufferSize()) {
+        changes |= RequestedLayerState::Changes::Geometry;
+    }
+    if (clientChanges & layer_state_t::HIERARCHY_CHANGES)
+        changes |= RequestedLayerState::Changes::Hierarchy;
+    if (clientChanges & layer_state_t::CONTENT_CHANGES)
+        changes |= RequestedLayerState::Changes::Content;
+    if (clientChanges & layer_state_t::GEOMETRY_CHANGES)
+        changes |= RequestedLayerState::Changes::Geometry;
+
+    if (clientState.what & layer_state_t::eColorTransformChanged) {
+        static const mat4 identityMatrix = mat4();
+        hasColorTransform = colorTransform != identityMatrix;
+    }
+    if (clientState.what & layer_state_t::eLayerChanged) {
+        changes |= RequestedLayerState::Changes::Z;
+    }
+    if (clientState.what & layer_state_t::eReparent) {
+        changes |= RequestedLayerState::Changes::Parent;
+        parentId = getLayerIdFromSurfaceControl(clientState.parentSurfaceControlForChild);
+        parentSurfaceControlForChild = nullptr;
+    }
+    if (clientState.what & layer_state_t::eRelativeLayerChanged) {
+        changes |= RequestedLayerState::Changes::RelativeParent;
+        relativeParentId = getLayerIdFromSurfaceControl(clientState.relativeLayerSurfaceControl);
+        isRelativeOf = true;
+        relativeLayerSurfaceControl = nullptr;
+    }
+    if ((clientState.what & layer_state_t::eLayerChanged ||
+         (clientState.what & layer_state_t::eReparent && parentId == UNASSIGNED_LAYER_ID)) &&
+        isRelativeOf) {
+        // clear out relz data
+        relativeParentId = UNASSIGNED_LAYER_ID;
+        isRelativeOf = false;
+        changes |= RequestedLayerState::Changes::RelativeParent;
+    }
+    if (clientState.what & layer_state_t::eReparent && parentId == relativeParentId) {
+        // provide a hint that we are are now a direct child and not a relative child.
+        changes |= RequestedLayerState::Changes::RelativeParent;
+    }
+    if (clientState.what & layer_state_t::eInputInfoChanged) {
+        wp<IBinder>& touchableRegionCropHandle =
+                windowInfoHandle->editInfo()->touchableRegionCropHandle;
+        touchCropId = LayerHandle::getLayerId(touchableRegionCropHandle.promote());
+        changes |= RequestedLayerState::Changes::Input;
+        touchableRegionCropHandle.clear();
+    }
+    if (clientState.what & layer_state_t::eStretchChanged) {
+        stretchEffect.sanitize();
+    }
+
+    if (clientState.what & layer_state_t::eHasListenerCallbacksChanged) {
+        // TODO(b/238781169) handle callbacks
+    }
+
+    if (clientState.what & layer_state_t::eBufferChanged) {
+        externalTexture = resolvedComposerState.externalTexture;
+        hwcBufferSlot = resolvedComposerState.hwcBufferSlot;
+    }
+
+    if (clientState.what & layer_state_t::ePositionChanged) {
+        requestedTransform.set(x, y);
+    }
+
+    if (clientState.what & layer_state_t::eMatrixChanged) {
+        requestedTransform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+    }
+}
+
+ui::Transform RequestedLayerState::getTransform() const {
+    if ((flags & layer_state_t::eIgnoreDestinationFrame) || destinationFrame.isEmpty()) {
+        // If destination frame is not set, use the requested transform set via
+        // Transaction::setPosition and Transaction::setMatrix.
+        return requestedTransform;
+    }
+
+    Rect destRect = destinationFrame;
+    int32_t destW = destRect.width();
+    int32_t destH = destRect.height();
+    if (destRect.left < 0) {
+        destRect.left = 0;
+        destRect.right = destW;
+    }
+    if (destRect.top < 0) {
+        destRect.top = 0;
+        destRect.bottom = destH;
+    }
+
+    if (!externalTexture) {
+        ui::Transform transform;
+        transform.set(static_cast<float>(destRect.left), static_cast<float>(destRect.top));
+        return transform;
+    }
+
+    uint32_t bufferWidth = externalTexture->getWidth();
+    uint32_t bufferHeight = externalTexture->getHeight();
+    // Undo any transformations on the buffer.
+    if (bufferTransform & ui::Transform::ROT_90) {
+        std::swap(bufferWidth, bufferHeight);
+    }
+    // TODO(b/238781169) remove dep
+    uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+    if (transformToDisplayInverse) {
+        if (invTransform & ui::Transform::ROT_90) {
+            std::swap(bufferWidth, bufferHeight);
+        }
+    }
+
+    float sx = static_cast<float>(destW) / static_cast<float>(bufferWidth);
+    float sy = static_cast<float>(destH) / static_cast<float>(bufferHeight);
+    ui::Transform transform;
+    transform.set(sx, 0, 0, sy);
+    transform.set(static_cast<float>(destRect.left), static_cast<float>(destRect.top));
+    return transform;
+}
+
+std::string RequestedLayerState::getDebugString() const {
+    return "[" + std::to_string(id) + "]" + name + ",parent=" + layerIdToString(parentId) +
+            ",relativeParent=" + layerIdToString(relativeParentId) +
+            ",isRelativeOf=" + std::to_string(isRelativeOf) +
+            ",mirrorId=" + layerIdToString(mirrorId) +
+            ",handleAlive=" + std::to_string(handleAlive);
+}
+
+std::string RequestedLayerState::getDebugStringShort() const {
+    return "[" + std::to_string(id) + "]" + name;
+}
+
+bool RequestedLayerState::canBeDestroyed() const {
+    return !handleAlive && parentId == UNASSIGNED_LAYER_ID;
+}
+bool RequestedLayerState::isRoot() const {
+    return canBeRoot && parentId == UNASSIGNED_LAYER_ID;
+}
+bool RequestedLayerState::isHiddenByPolicy() const {
+    return (flags & layer_state_t::eLayerHidden) == layer_state_t::eLayerHidden;
+};
+half4 RequestedLayerState::getColor() const {
+    if ((sidebandStream != nullptr) || (externalTexture != nullptr)) {
+        return {0._hf, 0._hf, 0._hf, color.a};
+    }
+    return color;
+}
+Rect RequestedLayerState::getBufferSize() const {
+    // for buffer state layers we use the display frame size as the buffer size.
+    if (!externalTexture) {
+        return Rect::INVALID_RECT;
+    }
+
+    uint32_t bufWidth = externalTexture->getWidth();
+    uint32_t bufHeight = externalTexture->getHeight();
+
+    // Undo any transformations on the buffer and return the result.
+    if (bufferTransform & ui::Transform::ROT_90) {
+        std::swap(bufWidth, bufHeight);
+    }
+
+    if (transformToDisplayInverse) {
+        // TODO(b/238781169) pass in display metrics (would be useful for input info as well
+        uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+        if (invTransform & ui::Transform::ROT_90) {
+            std::swap(bufWidth, bufHeight);
+        }
+    }
+
+    return Rect(0, 0, static_cast<int32_t>(bufWidth), static_cast<int32_t>(bufHeight));
+}
+
+Rect RequestedLayerState::getCroppedBufferSize() const {
+    Rect size = getBufferSize();
+    if (!crop.isEmpty() && size.isValid()) {
+        size.intersect(crop, &size);
+    } else if (!crop.isEmpty()) {
+        size = crop;
+    }
+    return size;
+}
+
+Rect RequestedLayerState::getBufferCrop() const {
+    // this is the crop rectangle that applies to the buffer
+    // itself (as opposed to the window)
+    if (!bufferCrop.isEmpty()) {
+        // if the buffer crop is defined, we use that
+        return bufferCrop;
+    } else if (externalTexture != nullptr) {
+        // otherwise we use the whole buffer
+        return externalTexture->getBounds();
+    } else {
+        // if we don't have a buffer yet, we use an empty/invalid crop
+        return Rect();
+    }
+}
+
+aidl::android::hardware::graphics::composer3::Composition RequestedLayerState::getCompositionType()
+        const {
+    using aidl::android::hardware::graphics::composer3::Composition;
+    // TODO(b/238781169) check about sidestream ready flag
+    if (sidebandStream.get()) {
+        return Composition::SIDEBAND;
+    }
+    if (!externalTexture) {
+        return Composition::SOLID_COLOR;
+    }
+    if (flags & layer_state_t::eLayerIsDisplayDecoration) {
+        return Composition::DISPLAY_DECORATION;
+    }
+    if (potentialCursor) {
+        return Composition::CURSOR;
+    }
+    return Composition::DEVICE;
+}
+
+Rect RequestedLayerState::reduce(const Rect& win, const Region& exclude) {
+    if (CC_LIKELY(exclude.isEmpty())) {
+        return win;
+    }
+    if (exclude.isRect()) {
+        return win.reduce(exclude.getBounds());
+    }
+    return Region(win).subtract(exclude).getBounds();
+}
+
+} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
new file mode 100644
index 0000000..0ddf5e2
--- /dev/null
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <ftl/flags.h>
+#include <gui/LayerState.h>
+#include <renderengine/ExternalTexture.h>
+
+#include "LayerCreationArgs.h"
+#include "TransactionState.h"
+
+namespace android::surfaceflinger::frontend {
+
+// Stores client requested states for a layer.
+// This struct does not store any other states or states pertaining to
+// other layers. Links to other layers that are part of the client
+// requested state such as parent are translated to layer id so
+// we can avoid extending the lifetime of layer handles.
+struct RequestedLayerState : layer_state_t {
+    // Changes in state after merging with new state. This includes additional state
+    // changes found in layer_state_t::what.
+    enum class Changes : uint32_t {
+        Created = 1u << 0,
+        Destroyed = 1u << 1,
+        Hierarchy = 1u << 2,
+        Geometry = 1u << 3,
+        Content = 1u << 4,
+        Input = 1u << 5,
+        Z = 1u << 6,
+        Mirror = 1u << 7,
+        Parent = 1u << 8,
+        RelativeParent = 1u << 9,
+        Metadata = 1u << 10,
+        Visibility = 1u << 11,
+    };
+    static Rect reduce(const Rect& win, const Region& exclude);
+    RequestedLayerState(const LayerCreationArgs&);
+    void merge(const ResolvedComposerState&);
+    ui::Transform getTransform() const;
+    bool canBeDestroyed() const;
+    bool isRoot() const;
+    bool isHiddenByPolicy() const;
+    half4 getColor() const;
+    Rect getBufferSize() const;
+    Rect getCroppedBufferSize() const;
+    Rect getBufferCrop() const;
+    std::string getDebugString() const;
+    std::string getDebugStringShort() const;
+    aidl::android::hardware::graphics::composer3::Composition getCompositionType() 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
+    // the same.
+    const uint32_t id;
+    const std::string name;
+    const bool canBeRoot = false;
+    const uint32_t layerCreationFlags;
+    const uint32_t textureName;
+    // The owner of the layer. If created from a non system process, it will be the calling uid.
+    // If created from a system process, the value can be passed in.
+    const uid_t ownerUid;
+    // The owner pid of the layer. If created from a non system process, it will be the calling pid.
+    // If created from a system process, the value can be passed in.
+    const pid_t ownerPid;
+    bool dataspaceRequested;
+    bool hasColorTransform;
+    bool premultipliedAlpha{true};
+    // This layer can be a cursor on some displays.
+    bool potentialCursor{false};
+    bool protectedByApp{false}; // application requires protected path to external sink
+    ui::Transform requestedTransform;
+    std::shared_ptr<FenceTime> acquireFenceTime;
+    std::shared_ptr<renderengine::ExternalTexture> externalTexture;
+    int hwcBufferSlot = 0;
+
+    // book keeping states
+    bool handleAlive = true;
+    bool isRelativeOf = false;
+    uint32_t parentId = UNASSIGNED_LAYER_ID;
+    uint32_t relativeParentId = UNASSIGNED_LAYER_ID;
+    uint32_t mirrorId = UNASSIGNED_LAYER_ID;
+    uint32_t touchCropId = UNASSIGNED_LAYER_ID;
+    uint32_t bgColorLayerId = UNASSIGNED_LAYER_ID;
+    ftl::Flags<RequestedLayerState::Changes> changes;
+};
+
+} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/SwapErase.h b/services/surfaceflinger/FrontEnd/SwapErase.h
new file mode 100644
index 0000000..f672f99
--- /dev/null
+++ b/services/surfaceflinger/FrontEnd/SwapErase.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <vector>
+
+namespace android::surfaceflinger::frontend {
+// Erases the first element in vec that matches value. This is a more optimal way to
+// remove an element from a vector that avoids relocating all the elements after the one
+// that is erased.
+template <typename T>
+void swapErase(std::vector<T>& vec, const T& value) {
+    auto it = std::find(vec.begin(), vec.end(), value);
+    if (it != vec.end()) {
+        std::iter_swap(it, vec.end() - 1);
+        vec.erase(vec.end() - 1);
+    }
+}
+
+// Similar to swapErase(std::vector<T>& vec, const T& value) but erases the first element
+// that returns true for predicate.
+template <typename T, class P>
+void swapErase(std::vector<T>& vec, P predicate) {
+    auto it = std::find_if(vec.begin(), vec.end(), predicate);
+    if (it != vec.end()) {
+        std::iter_swap(it, vec.end() - 1);
+        vec.erase(vec.end() - 1);
+    }
+}
+
+} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 7669bab..f743896 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -83,6 +83,7 @@
 } // namespace frametimeline
 
 class Layer : public virtual RefBase {
+public:
     // The following constants represent priority of the window. SF uses this information when
     // deciding which window has a priority when deciding about the refresh rate of the screen.
     // Priority 0 is considered the highest priority. -1 means that the priority is unset.
@@ -94,7 +95,6 @@
     // Windows that are not in focus, but voted for a specific mode ID.
     static constexpr int32_t PRIORITY_NOT_FOCUSED_WITH_MODE = 2;
 
-public:
     enum { // flags for doTransaction()
         eDontUpdateGeometryState = 0x00000001,
         eVisibleRegion = 0x00000002,
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index d88da4d..26c0d8e 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -92,6 +92,7 @@
         "LayerHistoryTest.cpp",
         "LayerInfoTest.cpp",
         "LayerMetadataTest.cpp",
+        "LayerLifecycleManagerTest.cpp",
         "LayerTest.cpp",
         "LayerTestUtils.cpp",
         "MessageQueueTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
new file mode 100644
index 0000000..89440a6
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -0,0 +1,453 @@
+/*
+ * 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/LayerLifecycleManager.h"
+#include "Layer.h"
+#include "gui/SurfaceComposerClient.h"
+
+using namespace android::surfaceflinger;
+
+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 \
+    /data/nativetest/libsurfaceflinger_unittest/libsurfaceflinger_unittest \
+    --gtest_filter="LayerLifecycleManagerTest.*" --gtest_repeat=100 \
+    --gtest_shuffle \
+    --gtest_brief=1
+*/
+class ExpectLayerLifecycleListener : public LayerLifecycleManager::ILifecycleListener {
+public:
+    void onLayerAdded(const RequestedLayerState& layer) override {
+        mActualLayersAdded.emplace(layer.id);
+    };
+    void onLayerDestroyed(const RequestedLayerState& layer) override {
+        mActualLayersDestroyed.emplace(layer.id);
+    };
+
+    void expectLayersAdded(const std::unordered_set<uint32_t>& expectedLayersAdded) {
+        EXPECT_EQ(expectedLayersAdded, mActualLayersAdded);
+        mActualLayersAdded.clear();
+    }
+    void expectLayersDestroyed(const std::unordered_set<uint32_t>& expectedLayersDestroyed) {
+        EXPECT_EQ(expectedLayersDestroyed, mActualLayersDestroyed);
+        mActualLayersDestroyed.clear();
+    }
+
+    std::unordered_set<uint32_t> mActualLayersAdded;
+    std::unordered_set<uint32_t> mActualLayersDestroyed;
+};
+
+class LayerLifecycleManagerTest : public testing::Test {
+protected:
+    std::unique_ptr<RequestedLayerState> rootLayer(uint32_t id) {
+        return std::make_unique<RequestedLayerState>(
+                createArgs(/*id=*/id, /*canBeRoot=*/true, /*parent=*/nullptr, /*mirror=*/nullptr));
+    }
+
+    std::unique_ptr<RequestedLayerState> childLayer(uint32_t id, uint32_t parentId) {
+        mHandles[parentId] = sp<LayerHandle>::make(parentId);
+        return std::make_unique<RequestedLayerState>(createArgs(/*id=*/id, /*canBeRoot=*/false,
+                                                                /*parent=*/mHandles[parentId],
+                                                                /*mirror=*/nullptr));
+    }
+
+    TransactionState reparentLayer(uint32_t id, uint32_t newParentId) {
+        TransactionState transaction;
+        transaction.states.push_back({});
+
+        if (newParentId == UNASSIGNED_LAYER_ID) {
+            transaction.states.front().state.parentSurfaceControlForChild = nullptr;
+        } else {
+            transaction.states.front().state.parentSurfaceControlForChild =
+                    sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(),
+                                             sp<LayerHandle>::make(newParentId),
+                                             static_cast<int32_t>(newParentId), "Test");
+        }
+        transaction.states.front().state.what = layer_state_t::eReparent;
+        transaction.states.front().state.surface = sp<LayerHandle>::make(id);
+        return transaction;
+    }
+
+    TransactionState setLayer(uint32_t id, int32_t z) {
+        TransactionState transaction;
+        transaction.states.push_back({});
+        transaction.states.front().state.z = z;
+        transaction.states.front().state.what = layer_state_t::eLayerChanged;
+        transaction.states.front().state.surface = sp<LayerHandle>::make(id);
+        return transaction;
+    }
+
+    TransactionState makeRelative(uint32_t id, uint32_t relativeParentId) {
+        TransactionState transaction;
+        transaction.states.push_back({});
+
+        if (relativeParentId == UNASSIGNED_LAYER_ID) {
+            transaction.states.front().state.relativeLayerSurfaceControl = nullptr;
+        } else {
+            transaction.states.front().state.relativeLayerSurfaceControl =
+                    sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(),
+                                             sp<LayerHandle>::make(relativeParentId),
+                                             static_cast<int32_t>(relativeParentId), "Test");
+        }
+        transaction.states.front().state.what = layer_state_t::eRelativeLayerChanged;
+        transaction.states.front().state.surface = sp<LayerHandle>::make(id);
+        return transaction;
+    }
+
+    RequestedLayerState* getRequestedLayerState(LayerLifecycleManager& lifecycleManager,
+                                                uint32_t layerId) {
+        return lifecycleManager.getLayerFromId(layerId);
+    }
+
+    std::unordered_map<uint32_t, sp<LayerHandle>> mHandles;
+};
+
+TEST_F(LayerLifecycleManagerTest, addLayers) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    layers.emplace_back(rootLayer(3));
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.onHandlesDestroyed({1, 2, 3});
+    EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    lifecycleManager.commitChanges();
+    EXPECT_FALSE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    listener->expectLayersAdded({1, 2, 3});
+    listener->expectLayersDestroyed({1, 2, 3});
+}
+
+TEST_F(LayerLifecycleManagerTest, updateLayerStates) {
+    LayerLifecycleManager lifecycleManager;
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    lifecycleManager.addLayers(std::move(layers));
+
+    std::vector<TransactionState> transactions;
+    transactions.emplace_back();
+    transactions.back().states.push_back({});
+    transactions.back().states.front().state.z = 2;
+    transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
+    sp<LayerHandle> handle = sp<LayerHandle>::make(1u);
+    transactions.back().states.front().state.surface = handle;
+    lifecycleManager.applyTransactions(transactions);
+    transactions.clear();
+
+    auto& managedLayers = lifecycleManager.getLayers();
+    ASSERT_EQ(managedLayers.size(), 1u);
+
+    EXPECT_EQ(managedLayers.front()->z, 2);
+    EXPECT_TRUE(managedLayers.front()->changes.test(RequestedLayerState::Changes::Z));
+
+    EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    lifecycleManager.commitChanges();
+    EXPECT_FALSE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    ASSERT_EQ(managedLayers.size(), 1u);
+    EXPECT_FALSE(managedLayers.front()->changes.test(RequestedLayerState::Changes::Z));
+
+    // apply transactions that do not affect the hierarchy
+    transactions.emplace_back();
+    transactions.back().states.push_back({});
+    transactions.back().states.front().state.backgroundBlurRadius = 22;
+    transactions.back().states.front().state.what = layer_state_t::eBackgroundBlurRadiusChanged;
+    transactions.back().states.front().state.surface = handle;
+    lifecycleManager.applyTransactions(transactions);
+    EXPECT_FALSE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    lifecycleManager.commitChanges();
+    EXPECT_FALSE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    EXPECT_EQ(managedLayers.front()->backgroundBlurRadius, 22u);
+}
+
+TEST_F(LayerLifecycleManagerTest, layerWithoutHandleIsDestroyed) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.onHandlesDestroyed({1});
+    lifecycleManager.commitChanges();
+
+    SCOPED_TRACE("layerWithoutHandleIsDestroyed");
+    listener->expectLayersAdded({1, 2});
+    listener->expectLayersDestroyed({1});
+}
+
+TEST_F(LayerLifecycleManagerTest, rootLayerWithoutHandleIsDestroyed) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.onHandlesDestroyed({1});
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2});
+    listener->expectLayersDestroyed({1});
+}
+
+TEST_F(LayerLifecycleManagerTest, offscreenLayerIsDestroyed) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    layers.emplace_back(childLayer(3, /*parent*/ 2));
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2, 3});
+    listener->expectLayersDestroyed({});
+
+    lifecycleManager.applyTransactions({reparentLayer(3, UNASSIGNED_LAYER_ID)});
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({});
+    listener->expectLayersDestroyed({});
+
+    lifecycleManager.onHandlesDestroyed({3});
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({});
+    listener->expectLayersDestroyed({3});
+}
+
+TEST_F(LayerLifecycleManagerTest, offscreenChildLayerWithHandleIsNotDestroyed) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    layers.emplace_back(childLayer(3, /*parent*/ 2));
+    layers.emplace_back(childLayer(4, /*parent*/ 3));
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2, 3, 4});
+    listener->expectLayersDestroyed({});
+
+    lifecycleManager.applyTransactions({reparentLayer(3, UNASSIGNED_LAYER_ID)});
+    lifecycleManager.onHandlesDestroyed({3});
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({});
+    listener->expectLayersDestroyed({3});
+}
+
+TEST_F(LayerLifecycleManagerTest, offscreenChildLayerWithoutHandleIsDestroyed) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    layers.emplace_back(childLayer(3, /*parent*/ 2));
+    layers.emplace_back(childLayer(4, /*parent*/ 3));
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2, 3, 4});
+    listener->expectLayersDestroyed({});
+
+    lifecycleManager.applyTransactions({reparentLayer(3, UNASSIGNED_LAYER_ID)});
+    lifecycleManager.onHandlesDestroyed({3, 4});
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({});
+    listener->expectLayersDestroyed({3, 4});
+}
+
+TEST_F(LayerLifecycleManagerTest, reparentingDoesNotAffectRelativeZ) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    layers.emplace_back(childLayer(3, /*parent*/ 2));
+    layers.emplace_back(childLayer(4, /*parent*/ 3));
+
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2, 3, 4});
+    listener->expectLayersDestroyed({});
+
+    lifecycleManager.applyTransactions({makeRelative(4, 1)});
+    EXPECT_TRUE(getRequestedLayerState(lifecycleManager, 4)->isRelativeOf);
+    lifecycleManager.applyTransactions({reparentLayer(4, 2)});
+    EXPECT_TRUE(getRequestedLayerState(lifecycleManager, 4)->isRelativeOf);
+
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({});
+    listener->expectLayersDestroyed({});
+}
+
+TEST_F(LayerLifecycleManagerTest, reparentingToNullRemovesRelativeZ) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    layers.emplace_back(childLayer(3, /*parent*/ 2));
+    layers.emplace_back(childLayer(4, /*parent*/ 3));
+
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2, 3, 4});
+    listener->expectLayersDestroyed({});
+
+    lifecycleManager.applyTransactions({makeRelative(4, 1)});
+    EXPECT_TRUE(getRequestedLayerState(lifecycleManager, 4)->isRelativeOf);
+    lifecycleManager.applyTransactions({reparentLayer(4, UNASSIGNED_LAYER_ID)});
+    EXPECT_FALSE(getRequestedLayerState(lifecycleManager, 4)->isRelativeOf);
+
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({});
+    listener->expectLayersDestroyed({});
+}
+
+TEST_F(LayerLifecycleManagerTest, setZRemovesRelativeZ) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    layers.emplace_back(rootLayer(2));
+    layers.emplace_back(childLayer(3, /*parent*/ 2));
+    layers.emplace_back(childLayer(4, /*parent*/ 3));
+
+    lifecycleManager.addLayers(std::move(layers));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2, 3, 4});
+    listener->expectLayersDestroyed({});
+
+    lifecycleManager.applyTransactions({makeRelative(4, 1)});
+    EXPECT_TRUE(getRequestedLayerState(lifecycleManager, 4)->isRelativeOf);
+    lifecycleManager.applyTransactions({setLayer(4, 1)});
+    EXPECT_FALSE(getRequestedLayerState(lifecycleManager, 4)->isRelativeOf);
+
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({});
+    listener->expectLayersDestroyed({});
+}
+
+TEST_F(LayerLifecycleManagerTest, canAddBackgroundLayer) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    lifecycleManager.addLayers(std::move(layers));
+
+    std::vector<TransactionState> transactions;
+    transactions.emplace_back();
+    transactions.back().states.push_back({});
+    transactions.back().states.front().state.bgColorAlpha = 0.5;
+    transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
+    sp<LayerHandle> handle = sp<LayerHandle>::make(1u);
+    transactions.back().states.front().state.surface = handle;
+    lifecycleManager.applyTransactions(transactions);
+
+    auto& managedLayers = lifecycleManager.getLayers();
+    ASSERT_EQ(managedLayers.size(), 2u);
+
+    EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2});
+    listener->expectLayersDestroyed({});
+    EXPECT_EQ(getRequestedLayerState(lifecycleManager, 2)->color.a, 0.5_hf);
+}
+
+TEST_F(LayerLifecycleManagerTest, canDestroyBackgroundLayer) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    lifecycleManager.addLayers(std::move(layers));
+
+    std::vector<TransactionState> transactions;
+    transactions.emplace_back();
+    transactions.back().states.push_back({});
+    transactions.back().states.front().state.bgColorAlpha = 0.5;
+    transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
+    sp<LayerHandle> handle = sp<LayerHandle>::make(1u);
+    transactions.back().states.front().state.surface = handle;
+    transactions.emplace_back();
+    transactions.back().states.push_back({});
+    transactions.back().states.front().state.bgColorAlpha = 0;
+    transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
+    transactions.back().states.front().state.surface = handle;
+
+    lifecycleManager.applyTransactions(transactions);
+
+    ASSERT_EQ(lifecycleManager.getLayers().size(), 1u);
+    ASSERT_EQ(lifecycleManager.getDestroyedLayers().size(), 1u);
+
+    EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2});
+    listener->expectLayersDestroyed({2});
+}
+
+TEST_F(LayerLifecycleManagerTest, onParentDestroyDestroysBackgroundLayer) {
+    LayerLifecycleManager lifecycleManager;
+    auto listener = std::make_shared<ExpectLayerLifecycleListener>();
+    lifecycleManager.addLifecycleListener(listener);
+
+    std::vector<std::unique_ptr<RequestedLayerState>> layers;
+    layers.emplace_back(rootLayer(1));
+    lifecycleManager.addLayers(std::move(layers));
+
+    std::vector<TransactionState> transactions;
+    transactions.emplace_back();
+    transactions.back().states.push_back({});
+    transactions.back().states.front().state.bgColorAlpha = 0.5;
+    transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
+    sp<LayerHandle> handle = sp<LayerHandle>::make(1u);
+    transactions.back().states.front().state.surface = handle;
+    transactions.emplace_back();
+    lifecycleManager.applyTransactions(transactions);
+    lifecycleManager.onHandlesDestroyed({1});
+
+    ASSERT_EQ(lifecycleManager.getLayers().size(), 0u);
+    ASSERT_EQ(lifecycleManager.getDestroyedLayers().size(), 2u);
+
+    EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
+    lifecycleManager.commitChanges();
+    listener->expectLayersAdded({1, 2});
+    listener->expectLayersDestroyed({1, 2});
+}
+
+} // namespace android::surfaceflinger::frontend