CE: Allow the final class to set the types used

Modifies the various CompositionEngine implementation classes so that
they no longer store instances of the state structures they manipulate.

Instead the implementation gets access to the state using an accessor,
which is only implemented by a final derived class type.

Doing this allows for implementation inheritance, where a derived
implementation can leverage covariance to work with a more specialized type.

Test: atest libsurfaceflinger_unittest libcompositionengine_test
Test: go/wm-smoke
Bug: 121291683
Change-Id: I26366900fc4c7869f4de91f25e43b3bec917f63d
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
index a8e05cb..9898e35 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
@@ -46,8 +46,8 @@
     virtual ~CompositionEngine();
 
     // Create a composition Display
-    virtual std::shared_ptr<Display> createDisplay(DisplayCreationArgs&&) = 0;
-    virtual std::shared_ptr<Layer> createLayer(LayerCreationArgs&&) = 0;
+    virtual std::shared_ptr<Display> createDisplay(const DisplayCreationArgs&) = 0;
+    virtual std::shared_ptr<Layer> createLayer(const LayerCreationArgs&) = 0;
 
     virtual HWComposer& getHwComposer() const = 0;
     virtual void setHwComposer(std::unique_ptr<HWComposer>) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h
index dbcd3bd..9193dc0 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Display.h
@@ -47,10 +47,10 @@
     virtual void disconnect() = 0;
 
     // Creates a render color mode for the display
-    virtual void createDisplayColorProfile(DisplayColorProfileCreationArgs&&) = 0;
+    virtual void createDisplayColorProfile(const DisplayColorProfileCreationArgs&) = 0;
 
     // Creates a render surface for the display
-    virtual void createRenderSurface(RenderSurfaceCreationArgs&&) = 0;
+    virtual void createRenderSurface(const RenderSurfaceCreationArgs&) = 0;
 
 protected:
     ~Display() = default;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
index 0778936..ced4227 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
@@ -30,9 +30,6 @@
  * A parameter object for creating Display instances
  */
 struct DisplayCreationArgs {
-    // True if this display is secure
-    bool isSecure = false;
-
     // True if this display is a virtual display
     bool isVirtual = false;
 
@@ -54,17 +51,13 @@
  *
  * Prefer:
  *
- *  DisplayCreationArgsBuilder().setIsSecure(false).setIsVirtual(false)
+ *  DisplayCreationArgsBuilder().setIsVirtual(false)
  *      .setDisplayId(displayId).build();
  */
 class DisplayCreationArgsBuilder {
 public:
     DisplayCreationArgs build() { return std::move(mArgs); }
 
-    DisplayCreationArgsBuilder& setIsSecure(bool isSecure) {
-        mArgs.isSecure = isSecure;
-        return *this;
-    }
     DisplayCreationArgsBuilder& setIsVirtual(bool isVirtual) {
         mArgs.isVirtual = isVirtual;
         return *this;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index d374baa..3830b07 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -162,12 +162,6 @@
     virtual std::unique_ptr<OutputLayer> createOutputLayer(const std::shared_ptr<Layer>&,
                                                            const sp<LayerFE>&) const = 0;
 
-    // Gets the OutputLayer corresponding to the input Layer instance from the
-    // current ordered set of output layers. If there is no such layer, a new
-    // one is created and returned.
-    virtual std::unique_ptr<OutputLayer> getOrCreateOutputLayer(std::shared_ptr<Layer>,
-                                                                sp<LayerFE>) = 0;
-
     // Sets the new ordered set of output layers for this output
     virtual void setOutputLayersOrderedByZ(OutputLayers&&) = 0;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index 6859846..5ce2fdc 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -78,7 +78,7 @@
 
     // Queues the drawn buffer for consumption by HWC. readyFence is the fence
     // which will fire when the buffer is ready for consumption.
-    virtual void queueBuffer(base::unique_fd&& readyFence) = 0;
+    virtual void queueBuffer(base::unique_fd readyFence) = 0;
 
     // Called after the HWC calls are made to present the display
     virtual void onPresentDisplayCompleted() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
index 6340b14..76798f1 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
@@ -26,9 +26,9 @@
     ~CompositionEngine() override;
 
     std::shared_ptr<compositionengine::Display> createDisplay(
-            compositionengine::DisplayCreationArgs&&) override;
+            const compositionengine::DisplayCreationArgs&) override;
     std::shared_ptr<compositionengine::Layer> createLayer(
-            compositionengine::LayerCreationArgs&&) override;
+            const compositionengine::LayerCreationArgs&) override;
 
     HWComposer& getHwComposer() const override;
     void setHwComposer(std::unique_ptr<HWComposer>) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index b5d8325..45a604f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <compositionengine/Display.h>
+#include <compositionengine/DisplayCreationArgs.h>
 #include <compositionengine/impl/Output.h>
 
 #include <memory>
@@ -29,36 +30,37 @@
 
 class CompositionEngine;
 
-struct DisplayCreationArgs;
-
 namespace impl {
 
-class Display : public compositionengine::impl::Output, public compositionengine::Display {
+// The implementation class contains the common implementation, but does not
+// actually contain the final display state.
+class Display : public compositionengine::impl::Output, public virtual compositionengine::Display {
 public:
-    Display(const CompositionEngine&, compositionengine::DisplayCreationArgs&&);
+    explicit Display(const compositionengine::DisplayCreationArgs&);
     virtual ~Display();
 
     // compositionengine::Output overrides
     void dump(std::string&) const override;
     std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
-            const std::shared_ptr<Layer>&, const sp<LayerFE>&) const override;
+            const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const override;
     using compositionengine::impl::Output::setReleasedLayers;
-    void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) override;
-    void setColorTransform(const compositionengine::CompositionRefreshArgs&) override;
+    void setReleasedLayers(const CompositionRefreshArgs&) override;
+    void setColorTransform(const CompositionRefreshArgs&) override;
     void setColorProfile(const ColorProfile&) override;
     void chooseCompositionStrategy() override;
     bool getSkipColorTransform() const override;
     compositionengine::Output::FrameFences presentAndGetFrameFences() override;
     void setExpensiveRenderingExpected(bool) override;
-    void finishFrame(const compositionengine::CompositionRefreshArgs&) override;
+    void finishFrame(const CompositionRefreshArgs&) override;
 
     // compositionengine::Display overrides
     const std::optional<DisplayId>& getId() const override;
     bool isSecure() const override;
     bool isVirtual() const override;
     void disconnect() override;
-    void createDisplayColorProfile(compositionengine::DisplayColorProfileCreationArgs&&) override;
-    void createRenderSurface(compositionengine::RenderSurfaceCreationArgs&&) override;
+    void createDisplayColorProfile(
+            const compositionengine::DisplayColorProfileCreationArgs&) override;
+    void createRenderSurface(const compositionengine::RenderSurfaceCreationArgs&) override;
 
     // Internal helpers used by chooseCompositionStrategy()
     using ChangedTypes = android::HWComposer::DeviceRequestedChanges::ChangedTypes;
@@ -76,8 +78,18 @@
     Hwc2::PowerAdvisor* const mPowerAdvisor{nullptr};
 };
 
+// This template factory function standardizes the implementation details of the
+// final class using the types actually required by the implementation. This is
+// not possible to do in the base class as those types may not even be visible
+// to the base code.
+template <typename BaseDisplay, typename CompositionEngine, typename DisplayCreationArgs>
+std::shared_ptr<BaseDisplay> createDisplayTemplated(const CompositionEngine& compositionEngine,
+                                                    const DisplayCreationArgs& args) {
+    return createOutputTemplated<BaseDisplay>(compositionEngine, args);
+}
+
 std::shared_ptr<Display> createDisplay(const compositionengine::CompositionEngine&,
-                                       compositionengine::DisplayCreationArgs&&);
+                                       const compositionengine::DisplayCreationArgs&);
 
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h
index e84a36e..9bc0e68 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h
@@ -33,7 +33,7 @@
 
 class DisplayColorProfile : public compositionengine::DisplayColorProfile {
 public:
-    DisplayColorProfile(DisplayColorProfileCreationArgs&&);
+    DisplayColorProfile(const DisplayColorProfileCreationArgs&);
     ~DisplayColorProfile() override;
 
     bool isValid() const override;
@@ -91,7 +91,7 @@
 };
 
 std::unique_ptr<compositionengine::DisplayColorProfile> createDisplayColorProfile(
-        DisplayColorProfileCreationArgs&&);
+        const DisplayColorProfileCreationArgs&);
 
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
index d441c9c..46489fb 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
@@ -19,43 +19,66 @@
 #include <memory>
 
 #include <compositionengine/Layer.h>
-#include <compositionengine/LayerFECompositionState.h>
-#include <utils/RefBase.h>
+#include <compositionengine/LayerCreationArgs.h>
 #include <utils/StrongPointer.h>
 
 namespace android::compositionengine {
 
-class CompositionEngine;
-class LayerFE;
-
 struct LayerCreationArgs;
 
 namespace impl {
 
-class Display;
-
-class Layer : public compositionengine::Layer {
+// The implementation class contains the common implementation, but does not
+// actually contain the final layer state.
+class Layer : public virtual compositionengine::Layer {
 public:
-    Layer(const CompositionEngine&, compositionengine::LayerCreationArgs&&);
     ~Layer() override;
 
-    sp<LayerFE> getLayerFE() const override;
+    // compositionengine::Layer overrides
+    void dump(std::string&) const override;
 
-    const LayerFECompositionState& getFEState() const override;
-    LayerFECompositionState& editFEState() override;
-
-    void dump(std::string& result) const override;
-
-private:
-    const compositionengine::CompositionEngine& mCompositionEngine;
-    const wp<LayerFE> mLayerFE;
-
-    // State obtained from calls to LayerFE::getCompositionState
-    LayerFECompositionState mFrontEndState;
+protected:
+    // Implemented by the final implementation for the final state it uses.
+    virtual void dumpFEState(std::string&) const = 0;
 };
 
-std::shared_ptr<compositionengine::Layer> createLayer(const compositionengine::CompositionEngine&,
-                                                      compositionengine::LayerCreationArgs&&);
+// This template factory function standardizes the implementation details of the
+// final class using the types actually required by the implementation. This is
+// not possible to do in the base class as those types may not even be visible
+// to the base code.
+template <typename BaseLayer, typename LayerCreationArgs>
+std::shared_ptr<BaseLayer> createLayerTemplated(const LayerCreationArgs& args) {
+    class Layer final : public BaseLayer {
+    public:
+// Clang incorrectly complains that these are unused.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-local-typedef"
+        using LayerFE = std::remove_pointer_t<decltype(
+                std::declval<decltype(std::declval<LayerCreationArgs>().layerFE)>().unsafe_get())>;
+        using LayerFECompositionState = std::remove_const_t<
+                std::remove_reference_t<decltype(std::declval<BaseLayer>().getFEState())>>;
+#pragma clang diagnostic pop
+
+        explicit Layer(const LayerCreationArgs& args) : mLayerFE(args.layerFE) {}
+        ~Layer() override = default;
+
+    private:
+        // compositionengine::Layer overrides
+        sp<compositionengine::LayerFE> getLayerFE() const override { return mLayerFE.promote(); }
+        const LayerFECompositionState& getFEState() const override { return mFrontEndState; }
+        LayerFECompositionState& editFEState() override { return mFrontEndState; }
+
+        // compositionengine::impl::Layer overrides
+        void dumpFEState(std::string& out) const override { mFrontEndState.dump(out); }
+
+        const wp<LayerFE> mLayerFE;
+        LayerFECompositionState mFrontEndState;
+    };
+
+    return std::make_shared<Layer>(args);
+}
+
+std::shared_ptr<Layer> createLayer(const LayerCreationArgs&);
 
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index fa6cd27..2766572 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -16,28 +16,24 @@
 
 #pragma once
 
+#include <compositionengine/CompositionEngine.h>
+#include <compositionengine/Output.h>
+#include <compositionengine/impl/OutputCompositionState.h>
+
 #include <memory>
 #include <utility>
 #include <vector>
 
-#include <compositionengine/Output.h>
-#include <compositionengine/impl/OutputCompositionState.h>
+namespace android::compositionengine::impl {
 
-namespace android::compositionengine {
-
-class CompositionEngine;
-class Layer;
-class OutputLayer;
-
-namespace impl {
-
+// The implementation class contains the common implementation, but does not
+// actually contain the final output state.
 class Output : public virtual compositionengine::Output {
 public:
-    Output(const CompositionEngine&);
     ~Output() override;
 
+    // compositionengine::Output overrides
     bool isValid() const override;
-
     void setCompositionEnabled(bool) override;
     void setProjection(const ui::Transform&, int32_t orientation, const Rect& frame,
                        const Rect& viewport, const Rect& scissor, bool needsFiltering) override;
@@ -58,9 +54,6 @@
     compositionengine::RenderSurface* getRenderSurface() const override;
     void setRenderSurface(std::unique_ptr<compositionengine::RenderSurface>) override;
 
-    const OutputCompositionState& getState() const override;
-    OutputCompositionState& editState() override;
-
     Region getDirtyRegion(bool repaintEverything) const override;
     bool belongsInOutput(std::optional<uint32_t>, bool) const override;
     bool belongsInOutput(const compositionengine::Layer*) const override;
@@ -69,19 +62,17 @@
             compositionengine::Layer*) const override;
     std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
             const std::shared_ptr<Layer>&, const sp<LayerFE>&) const override;
-    std::unique_ptr<compositionengine::OutputLayer> getOrCreateOutputLayer(
-            std::shared_ptr<compositionengine::Layer>, sp<LayerFE>) override;
     void setOutputLayersOrderedByZ(OutputLayers&&) override;
     const OutputLayers& getOutputLayersOrderedByZ() const override;
 
     void setReleasedLayers(ReleasedLayers&&) override;
     ReleasedLayers takeReleasedLayers() override;
 
-    void prepare(const compositionengine::CompositionRefreshArgs&, LayerFESet&) override;
-    void present(const compositionengine::CompositionRefreshArgs&) override;
+    void prepare(const CompositionRefreshArgs&, LayerFESet&) override;
+    void present(const CompositionRefreshArgs&) override;
 
-    void rebuildLayerStacks(const compositionengine::CompositionRefreshArgs&, LayerFESet&) override;
-    void collectVisibleLayers(const compositionengine::CompositionRefreshArgs&,
+    void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) override;
+    void collectVisibleLayers(const CompositionRefreshArgs&,
                               compositionengine::Output::CoverageState&) override;
     std::unique_ptr<compositionengine::OutputLayer> getOutputLayerIfVisible(
             std::shared_ptr<compositionengine::Layer>,
@@ -93,8 +84,8 @@
     void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;
     void beginFrame() override;
     void prepareFrame() override;
-    void devOptRepaintFlash(const compositionengine::CompositionRefreshArgs&) override;
-    void finishFrame(const compositionengine::CompositionRefreshArgs&) override;
+    void devOptRepaintFlash(const CompositionRefreshArgs&) override;
+    void finishFrame(const CompositionRefreshArgs&) override;
     std::optional<base::unique_fd> composeSurfaces(const Region&) override;
     void postFramebuffer() override;
 
@@ -104,7 +95,7 @@
     void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>);
 
 protected:
-    const CompositionEngine& getCompositionEngine() const;
+    virtual const CompositionEngine& getCompositionEngine() const = 0;
     std::unique_ptr<compositionengine::OutputLayer> takeOutputLayerForLayer(
             compositionengine::Layer*);
     void chooseCompositionStrategy() override;
@@ -117,18 +108,17 @@
     void setExpensiveRenderingExpected(bool enabled) override;
     void dumpBase(std::string&) const;
 
+    // Implemented by the final implementation for the final state it uses.
+    virtual void dumpState(std::string&) const = 0;
+
 private:
     void dirtyEntireOutput();
     ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const;
     compositionengine::Output::ColorProfile pickColorProfile(
             const compositionengine::CompositionRefreshArgs&) const;
 
-    const CompositionEngine& mCompositionEngine;
-
     std::string mName;
 
-    OutputCompositionState mState;
-
     std::unique_ptr<compositionengine::DisplayColorProfile> mDisplayColorProfile;
     std::unique_ptr<compositionengine::RenderSurface> mRenderSurface;
 
@@ -136,5 +126,46 @@
     ReleasedLayers mReleasedLayers;
 };
 
-} // namespace impl
-} // namespace android::compositionengine
+// This template factory function standardizes the implementation details of the
+// final class using the types actually required by the implementation. This is
+// not possible to do in the base class as those types may not even be visible
+// to the base code.
+template <typename BaseOutput, typename CompositionEngine, typename... Args>
+std::shared_ptr<BaseOutput> createOutputTemplated(const CompositionEngine& compositionEngine,
+                                                  Args... args) {
+    class Output final : public BaseOutput {
+    public:
+// Clang incorrectly complains that these are unused.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-local-typedef"
+
+        using OutputCompositionState = std::remove_const_t<
+                std::remove_reference_t<decltype(std::declval<BaseOutput>().getState())>>;
+
+#pragma clang diagnostic pop
+
+        explicit Output(const CompositionEngine& compositionEngine, Args... args)
+              : BaseOutput(std::forward<Args>(args)...), mCompositionEngine(compositionEngine) {}
+        ~Output() override = default;
+
+    private:
+        // compositionengine::Output overrides
+        const OutputCompositionState& getState() const override { return mState; }
+        OutputCompositionState& editState() override { return mState; }
+
+        // compositionengine::impl::Output overrides
+        const CompositionEngine& getCompositionEngine() const override {
+            return mCompositionEngine;
+        };
+        void dumpState(std::string& out) const override { mState.dump(out); }
+
+        const CompositionEngine& mCompositionEngine;
+        OutputCompositionState mState;
+    };
+
+    return std::make_shared<Output>(compositionEngine, std::forward<Args>(args)...);
+}
+
+std::shared_ptr<Output> createOutput(const compositionengine::CompositionEngine&);
+
+} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 1199fea..34dbfb7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -20,7 +20,6 @@
 #include <string>
 
 #include <compositionengine/OutputLayer.h>
-#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <ui/FloatRect.h>
 #include <ui/Rect.h>
 
@@ -32,21 +31,14 @@
 
 namespace impl {
 
-class OutputLayer : public compositionengine::OutputLayer {
+// The implementation class contains the common implementation, but does not
+// actually contain the final layer state.
+class OutputLayer : public virtual compositionengine::OutputLayer {
 public:
-    OutputLayer(const compositionengine::Output&, const std::shared_ptr<compositionengine::Layer>&,
-                const sp<compositionengine::LayerFE>&);
     ~OutputLayer() override;
 
     void setHwcLayer(std::shared_ptr<HWC2::Layer>) override;
 
-    const compositionengine::Output& getOutput() const override;
-    compositionengine::Layer& getLayer() const override;
-    compositionengine::LayerFE& getLayerFE() const override;
-
-    const OutputLayerCompositionState& getState() const override;
-    OutputLayerCompositionState& editState() override;
-
     void updateCompositionState(bool) override;
     void writeStateToHWC(bool) override;
     void writeCursorPositionToHWC() const override;
@@ -59,12 +51,16 @@
     void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override;
     bool needsFiltering() const override;
 
-    void dump(std::string& result) const override;
+    void dump(std::string&) const override;
 
     virtual FloatRect calculateOutputSourceCrop() const;
     virtual Rect calculateOutputDisplayFrame() const;
     virtual uint32_t calculateOutputRelativeBufferTransform() const;
 
+protected:
+    // Implemented by the final implementation for the final state it uses.
+    virtual void dumpState(std::string&) const = 0;
+
 private:
     Rect calculateInitialCrop() const;
     void writeOutputDependentGeometryStateToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition);
@@ -77,17 +73,60 @@
     void writeCompositionTypeToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition);
     void detectDisallowedCompositionTypeChange(Hwc2::IComposerClient::Composition from,
                                                Hwc2::IComposerClient::Composition to) const;
-
-    const compositionengine::Output& mOutput;
-    std::shared_ptr<compositionengine::Layer> mLayer;
-    sp<compositionengine::LayerFE> mLayerFE;
-
-    OutputLayerCompositionState mState;
 };
 
-std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
-        const compositionengine::Output&, const std::shared_ptr<compositionengine::Layer>&,
-        const sp<compositionengine::LayerFE>&);
+// This template factory function standardizes the implementation details of the
+// final class using the types actually required by the implementation. This is
+// not possible to do in the base class as those types may not even be visible
+// to the base code.
+template <typename BaseOutputLayer>
+std::unique_ptr<BaseOutputLayer> createOutputLayerTemplated(const Output& output,
+                                                            std::shared_ptr<Layer> layer,
+                                                            sp<LayerFE> layerFE) {
+    class OutputLayer final : public BaseOutputLayer {
+    public:
+// Clang incorrectly complains that these are unused.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-local-typedef"
+
+        using OutputLayerCompositionState = std::remove_const_t<
+                std::remove_reference_t<decltype(std::declval<BaseOutputLayer>().getState())>>;
+        using Output = std::remove_const_t<
+                std::remove_reference_t<decltype(std::declval<BaseOutputLayer>().getOutput())>>;
+        using Layer = std::remove_reference_t<decltype(std::declval<BaseOutputLayer>().getLayer())>;
+        using LayerFE =
+                std::remove_reference_t<decltype(std::declval<BaseOutputLayer>().getLayerFE())>;
+
+#pragma clang diagnostic pop
+
+        OutputLayer(const Output& output, const std::shared_ptr<Layer>& layer,
+                    const sp<LayerFE>& layerFE)
+              : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
+        ~OutputLayer() override = default;
+
+    private:
+        // compositionengine::OutputLayer overrides
+        const Output& getOutput() const override { return mOutput; }
+        Layer& getLayer() const override { return *mLayer; }
+        LayerFE& getLayerFE() const override { return *mLayerFE; }
+        const OutputLayerCompositionState& getState() const override { return mState; }
+        OutputLayerCompositionState& editState() override { return mState; }
+
+        // compositionengine::impl::OutputLayer overrides
+        void dumpState(std::string& out) const override { mState.dump(out); }
+
+        const Output& mOutput;
+        const std::shared_ptr<Layer> mLayer;
+        const sp<LayerFE> mLayerFE;
+        OutputLayerCompositionState mState;
+    };
+
+    return std::make_unique<OutputLayer>(output, layer, layerFE);
+}
+
+std::unique_ptr<OutputLayer> createOutputLayer(const compositionengine::Output&,
+                                               const std::shared_ptr<compositionengine::Layer>&,
+                                               const sp<LayerFE>&);
 
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 0a04462..692d78d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -39,7 +39,7 @@
 class RenderSurface : public compositionengine::RenderSurface {
 public:
     RenderSurface(const CompositionEngine&, compositionengine::Display&,
-                  compositionengine::RenderSurfaceCreationArgs&&);
+                  const compositionengine::RenderSurfaceCreationArgs&);
     ~RenderSurface() override;
 
     bool isValid() const override;
@@ -54,7 +54,7 @@
     status_t beginFrame(bool mustRecompose) override;
     void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) override;
     sp<GraphicBuffer> dequeueBuffer(base::unique_fd* bufferFence) override;
-    void queueBuffer(base::unique_fd&& readyFence) override;
+    void queueBuffer(base::unique_fd readyFence) override;
     void onPresentDisplayCompleted() override;
     void flip() override;
 
@@ -84,7 +84,7 @@
 
 std::unique_ptr<compositionengine::RenderSurface> createRenderSurface(
         const compositionengine::CompositionEngine&, compositionengine::Display&,
-        compositionengine::RenderSurfaceCreationArgs&&);
+        const compositionengine::RenderSurfaceCreationArgs&);
 
 } // namespace impl
 } // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
index e3254ac..af7efdd 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
@@ -32,8 +32,8 @@
     CompositionEngine();
     ~CompositionEngine() override;
 
-    MOCK_METHOD1(createDisplay, std::shared_ptr<Display>(DisplayCreationArgs&&));
-    MOCK_METHOD1(createLayer, std::shared_ptr<Layer>(LayerCreationArgs&&));
+    MOCK_METHOD1(createDisplay, std::shared_ptr<Display>(const DisplayCreationArgs&));
+    MOCK_METHOD1(createLayer, std::shared_ptr<Layer>(const LayerCreationArgs&));
 
     MOCK_CONST_METHOD0(getHwComposer, HWComposer&());
     MOCK_METHOD1(setHwComposer, void(std::unique_ptr<HWComposer>));
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
index d763aa6..57f33ae 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
@@ -38,8 +38,8 @@
 
     MOCK_METHOD0(disconnect, void());
 
-    MOCK_METHOD1(createDisplayColorProfile, void(DisplayColorProfileCreationArgs&&));
-    MOCK_METHOD1(createRenderSurface, void(RenderSurfaceCreationArgs&&));
+    MOCK_METHOD1(createDisplayColorProfile, void(const DisplayColorProfileCreationArgs&));
+    MOCK_METHOD1(createRenderSurface, void(const RenderSurfaceCreationArgs&));
 };
 
 } // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index ba6746a..ed4d492 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -39,7 +39,7 @@
     MOCK_METHOD1(beginFrame, status_t(bool mustRecompose));
     MOCK_METHOD2(prepareFrame, void(bool, bool));
     MOCK_METHOD1(dequeueBuffer, sp<GraphicBuffer>(base::unique_fd*));
-    MOCK_METHOD1(queueBuffer, void(base::unique_fd&&));
+    MOCK_METHOD1(queueBuffer, void(base::unique_fd));
     MOCK_METHOD0(onPresentDisplayCompleted, void());
     MOCK_METHOD0(flip, void());
     MOCK_CONST_METHOD1(dump, void(std::string& result));
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 8391458..abf73ad 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -39,12 +39,13 @@
 CompositionEngine::~CompositionEngine() = default;
 
 std::shared_ptr<compositionengine::Display> CompositionEngine::createDisplay(
-        DisplayCreationArgs&& args) {
-    return compositionengine::impl::createDisplay(*this, std::move(args));
+        const DisplayCreationArgs& args) {
+    return compositionengine::impl::createDisplay(*this, args);
 }
 
-std::shared_ptr<compositionengine::Layer> CompositionEngine::createLayer(LayerCreationArgs&& args) {
-    return compositionengine::impl::createLayer(*this, std::move(args));
+std::shared_ptr<compositionengine::Layer> CompositionEngine::createLayer(
+        const LayerCreationArgs& args) {
+    return compositionengine::impl::createLayer(args);
 }
 
 HWComposer& CompositionEngine::getHwComposer() const {
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index fe8fa21..87df858 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -34,17 +34,12 @@
 
 std::shared_ptr<Display> createDisplay(
         const compositionengine::CompositionEngine& compositionEngine,
-        compositionengine::DisplayCreationArgs&& args) {
-    return std::make_shared<Display>(compositionEngine, std::move(args));
+        const compositionengine::DisplayCreationArgs& args) {
+    return createDisplayTemplated<Display>(compositionEngine, args);
 }
 
-Display::Display(const CompositionEngine& compositionEngine, DisplayCreationArgs&& args)
-      : compositionengine::impl::Output(compositionEngine),
-        mIsVirtual(args.isVirtual),
-        mId(args.displayId),
-        mPowerAdvisor(args.powerAdvisor) {
-    editState().isSecure = args.isSecure;
-}
+Display::Display(const DisplayCreationArgs& args)
+      : mIsVirtual(args.isVirtual), mId(args.displayId), mPowerAdvisor(args.powerAdvisor) {}
 
 Display::~Display() = default;
 
@@ -125,13 +120,13 @@
     Output::dumpBase(out);
 }
 
-void Display::createDisplayColorProfile(DisplayColorProfileCreationArgs&& args) {
-    setDisplayColorProfile(compositionengine::impl::createDisplayColorProfile(std::move(args)));
+void Display::createDisplayColorProfile(const DisplayColorProfileCreationArgs& args) {
+    setDisplayColorProfile(compositionengine::impl::createDisplayColorProfile(args));
 }
 
-void Display::createRenderSurface(RenderSurfaceCreationArgs&& args) {
-    setRenderSurface(compositionengine::impl::createRenderSurface(getCompositionEngine(), *this,
-                                                                  std::move(args)));
+void Display::createRenderSurface(const RenderSurfaceCreationArgs& args) {
+    setRenderSurface(
+            compositionengine::impl::createRenderSurface(getCompositionEngine(), *this, args));
 }
 
 std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
diff --git a/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp b/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp
index 5ef9097..a7c4512 100644
--- a/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp
@@ -184,11 +184,11 @@
 } // anonymous namespace
 
 std::unique_ptr<compositionengine::DisplayColorProfile> createDisplayColorProfile(
-        DisplayColorProfileCreationArgs&& args) {
-    return std::make_unique<DisplayColorProfile>(std::move(args));
+        const DisplayColorProfileCreationArgs& args) {
+    return std::make_unique<DisplayColorProfile>(args);
 }
 
-DisplayColorProfile::DisplayColorProfile(DisplayColorProfileCreationArgs&& args)
+DisplayColorProfile::DisplayColorProfile(const DisplayColorProfileCreationArgs& args)
       : mHasWideColorGamut(args.hasWideColorGamut),
         mSupportedPerFrameMetadata(args.supportedPerFrameMetadata) {
     populateColorModes(args.hwcColorModes);
diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp
index 8a1cbe4..ecacaee 100644
--- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Layer.cpp
@@ -15,9 +15,8 @@
  */
 
 #include <android-base/stringprintf.h>
-#include <compositionengine/CompositionEngine.h>
-#include <compositionengine/LayerCreationArgs.h>
 #include <compositionengine/LayerFE.h>
+#include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/impl/Layer.h>
 
 namespace android::compositionengine {
@@ -26,38 +25,18 @@
 
 namespace impl {
 
-std::shared_ptr<compositionengine::Layer> createLayer(
-        const compositionengine::CompositionEngine& compositionEngine,
-        compositionengine::LayerCreationArgs&& args) {
-    return std::make_shared<Layer>(compositionEngine, std::move(args));
-}
-
-Layer::Layer(const CompositionEngine& compositionEngine, LayerCreationArgs&& args)
-      : mCompositionEngine(compositionEngine), mLayerFE(args.layerFE) {
-    static_cast<void>(mCompositionEngine); // Temporary use to prevent an unused warning
+std::shared_ptr<Layer> createLayer(const LayerCreationArgs& args) {
+    return compositionengine::impl::createLayerTemplated<Layer>(args);
 }
 
 Layer::~Layer() = default;
 
-sp<LayerFE> Layer::getLayerFE() const {
-    return mLayerFE.promote();
-}
-
-const compositionengine::LayerFECompositionState& Layer::getFEState() const {
-    return mFrontEndState;
-}
-
-compositionengine::LayerFECompositionState& Layer::editFEState() {
-    return mFrontEndState;
-}
-
 void Layer::dump(std::string& out) const {
     auto layerFE = getLayerFE();
     android::base::StringAppendF(&out, "* compositionengine::Layer %p (%s)\n", this,
                                  layerFE ? layerFE->getDebugName() : "<unknown>");
-
     out.append("    frontend:\n");
-    mFrontEndState.dump(out);
+    dumpFEState(out);
 }
 
 } // namespace impl
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 02ebc1f..c511306 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -25,7 +25,9 @@
 #include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/RenderSurface.h>
 #include <compositionengine/impl/Output.h>
+#include <compositionengine/impl/OutputCompositionState.h>
 #include <compositionengine/impl/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <renderengine/DisplaySettings.h>
 #include <renderengine/RenderEngine.h>
 #include <ui/DebugUtils.h>
@@ -61,15 +63,13 @@
 
 } // namespace
 
-Output::Output(const CompositionEngine& compositionEngine)
-      : mCompositionEngine(compositionEngine) {}
+std::shared_ptr<Output> createOutput(
+        const compositionengine::CompositionEngine& compositionEngine) {
+    return createOutputTemplated<Output>(compositionEngine);
+}
 
 Output::~Output() = default;
 
-const CompositionEngine& Output::getCompositionEngine() const {
-    return mCompositionEngine;
-}
-
 bool Output::isValid() const {
     return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface &&
             mRenderSurface->isValid();
@@ -84,22 +84,24 @@
 }
 
 void Output::setCompositionEnabled(bool enabled) {
-    if (mState.isEnabled == enabled) {
+    auto& outputState = editState();
+    if (outputState.isEnabled == enabled) {
         return;
     }
 
-    mState.isEnabled = enabled;
+    outputState.isEnabled = enabled;
     dirtyEntireOutput();
 }
 
 void Output::setProjection(const ui::Transform& transform, int32_t orientation, const Rect& frame,
                            const Rect& viewport, const Rect& scissor, bool needsFiltering) {
-    mState.transform = transform;
-    mState.orientation = orientation;
-    mState.scissor = scissor;
-    mState.frame = frame;
-    mState.viewport = viewport;
-    mState.needsFiltering = needsFiltering;
+    auto& outputState = editState();
+    outputState.transform = transform;
+    outputState.orientation = orientation;
+    outputState.scissor = scissor;
+    outputState.frame = frame;
+    outputState.viewport = viewport;
+    outputState.needsFiltering = needsFiltering;
 
     dirtyEntireOutput();
 }
@@ -107,44 +109,48 @@
 // TODO(b/121291683): Rename setSize() once more is moved.
 void Output::setBounds(const ui::Size& size) {
     mRenderSurface->setDisplaySize(size);
-    // TODO(b/121291683): Rename mState.size once more is moved.
-    mState.bounds = Rect(mRenderSurface->getSize());
+    // TODO(b/121291683): Rename outputState.size once more is moved.
+    editState().bounds = Rect(mRenderSurface->getSize());
 
     dirtyEntireOutput();
 }
 
 void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) {
-    mState.layerStackId = layerStackId;
-    mState.layerStackInternal = isInternal;
+    auto& outputState = editState();
+    outputState.layerStackId = layerStackId;
+    outputState.layerStackInternal = isInternal;
 
     dirtyEntireOutput();
 }
 
 void Output::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
-    if (!args.colorTransformMatrix || mState.colorTransformMatrix == *args.colorTransformMatrix) {
+    auto& colorTransformMatrix = editState().colorTransformMatrix;
+    if (!args.colorTransformMatrix || colorTransformMatrix == args.colorTransformMatrix) {
         return;
     }
 
-    mState.colorTransformMatrix = *args.colorTransformMatrix;
+    colorTransformMatrix = *args.colorTransformMatrix;
 
     dirtyEntireOutput();
 }
 
 void Output::setColorProfile(const ColorProfile& colorProfile) {
-    const ui::Dataspace targetDataspace =
+    ui::Dataspace targetDataspace =
             getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace,
                                                          colorProfile.colorSpaceAgnosticDataspace);
 
-    if (mState.colorMode == colorProfile.mode && mState.dataspace == colorProfile.dataspace &&
-        mState.renderIntent == colorProfile.renderIntent &&
-        mState.targetDataspace == targetDataspace) {
+    auto& outputState = editState();
+    if (outputState.colorMode == colorProfile.mode &&
+        outputState.dataspace == colorProfile.dataspace &&
+        outputState.renderIntent == colorProfile.renderIntent &&
+        outputState.targetDataspace == targetDataspace) {
         return;
     }
 
-    mState.colorMode = colorProfile.mode;
-    mState.dataspace = colorProfile.dataspace;
-    mState.renderIntent = colorProfile.renderIntent;
-    mState.targetDataspace = targetDataspace;
+    outputState.colorMode = colorProfile.mode;
+    outputState.dataspace = colorProfile.dataspace;
+    outputState.renderIntent = colorProfile.renderIntent;
+    outputState.targetDataspace = targetDataspace;
 
     mRenderSurface->setBufferDataspace(colorProfile.dataspace);
 
@@ -166,7 +172,7 @@
 }
 
 void Output::dumpBase(std::string& out) const {
-    mState.dump(out);
+    dumpState(out);
 
     if (mDisplayColorProfile) {
         mDisplayColorProfile->dump(out);
@@ -212,7 +218,7 @@
 
 void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
     mRenderSurface = std::move(surface);
-    mState.bounds = Rect(mRenderSurface->getSize());
+    editState().bounds = Rect(mRenderSurface->getSize());
 
     dirtyEntireOutput();
 }
@@ -221,18 +227,11 @@
     mRenderSurface = std::move(surface);
 }
 
-const OutputCompositionState& Output::getState() const {
-    return mState;
-}
-
-OutputCompositionState& Output::editState() {
-    return mState;
-}
-
 Region Output::getDirtyRegion(bool repaintEverything) const {
-    Region dirty(mState.viewport);
+    const auto& outputState = getState();
+    Region dirty(outputState.viewport);
     if (!repaintEverything) {
-        dirty.andSelf(mState.dirtyRegion);
+        dirty.andSelf(outputState.dirtyRegion);
     }
     return dirty;
 }
@@ -240,8 +239,9 @@
 bool Output::belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const {
     // The layerStackId's must match, and also the layer must not be internal
     // only when not on an internal output.
-    return layerStackId && (*layerStackId == mState.layerStackId) &&
-            (!internalOnly || mState.layerStackInternal);
+    const auto& outputState = getState();
+    return layerStackId && (*layerStackId == outputState.layerStackId) &&
+            (!internalOnly || outputState.layerStackInternal);
 }
 
 bool Output::belongsInOutput(const compositionengine::Layer* layer) const {
@@ -274,15 +274,6 @@
     return nullptr;
 }
 
-std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
-        std::shared_ptr<compositionengine::Layer> layer, sp<compositionengine::LayerFE> layerFE) {
-    auto result = takeOutputLayerForLayer(layer.get());
-    if (!result) {
-        result = createOutputLayer(layer, layerFE);
-    }
-    return result;
-}
-
 std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
         const std::shared_ptr<compositionengine::Layer>& layer,
         const sp<compositionengine::LayerFE>& layerFE) const {
@@ -332,8 +323,10 @@
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
 
+    auto& outputState = editState();
+
     // Do nothing if this output is not enabled or there is no need to perform this update
-    if (!mState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) {
+    if (!outputState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) {
         return;
     }
 
@@ -342,12 +335,12 @@
     collectVisibleLayers(refreshArgs, coverage);
 
     // Compute the resulting coverage for this output, and store it for later
-    const ui::Transform& tr = mState.transform;
-    Region undefinedRegion{mState.bounds};
+    const ui::Transform& tr = outputState.transform;
+    Region undefinedRegion{outputState.bounds};
     undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));
 
-    mState.undefinedRegion = undefinedRegion;
-    mState.dirtyRegion.orSelf(coverage.dirtyRegion);
+    outputState.undefinedRegion = undefinedRegion;
+    outputState.dirtyRegion.orSelf(coverage.dirtyRegion);
 }
 
 void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
@@ -543,8 +536,9 @@
 
     // Peform the final check to see if this layer is visible on this output
     // TODO(b/121291683): Why does this not use visibleRegion? (see outputSpaceVisibleRegion below)
-    Region drawRegion(mState.transform.transform(visibleNonTransparentRegion));
-    drawRegion.andSelf(mState.bounds);
+    const auto& outputState = getState();
+    Region drawRegion(outputState.transform.transform(visibleNonTransparentRegion));
+    drawRegion.andSelf(outputState.bounds);
     if (drawRegion.isEmpty()) {
         return nullptr;
     }
@@ -560,8 +554,8 @@
     outputLayerState.visibleRegion = visibleRegion;
     outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
     outputLayerState.coveredRegion = coveredRegion;
-    outputLayerState.outputSpaceVisibleRegion =
-            mState.transform.transform(outputLayerState.visibleRegion.intersect(mState.viewport));
+    outputLayerState.outputSpaceVisibleRegion = outputState.transform.transform(
+            outputLayerState.visibleRegion.intersect(outputState.viewport));
 
     return result;
 }
@@ -706,9 +700,10 @@
 }
 
 void Output::beginFrame() {
+    auto& outputState = editState();
     const bool dirty = !getDirtyRegion(false).isEmpty();
     const bool empty = mOutputLayersOrderedByZ.empty();
-    const bool wasEmpty = !mState.lastCompositionHadVisibleLayers;
+    const bool wasEmpty = !outputState.lastCompositionHadVisibleLayers;
 
     // If nothing has changed (!dirty), don't recompose.
     // If something changed, but we don't currently have any visible layers,
@@ -729,7 +724,7 @@
     mRenderSurface->beginFrame(mustRecompose);
 
     if (mustRecompose) {
-        mState.lastCompositionHadVisibleLayers = !empty;
+        outputState.lastCompositionHadVisibleLayers = !empty;
     }
 }
 
@@ -737,13 +732,15 @@
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
 
-    if (!mState.isEnabled) {
+    const auto& outputState = getState();
+    if (!outputState.isEnabled) {
         return;
     }
 
     chooseCompositionStrategy();
 
-    mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition);
+    mRenderSurface->prepareFrame(outputState.usesClientComposition,
+                                 outputState.usesDeviceComposition);
 }
 
 void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
@@ -751,7 +748,7 @@
         return;
     }
 
-    if (mState.isEnabled) {
+    if (getState().isEnabled) {
         // transform the dirty region into this screen's coordinate space
         const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
         if (!dirtyRegion.isEmpty()) {
@@ -774,7 +771,7 @@
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
 
-    if (!mState.isEnabled) {
+    if (!getState().isEnabled) {
         return;
     }
 
@@ -793,32 +790,33 @@
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
 
+    const auto& outputState = getState();
     const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
-                                                      mState.usesClientComposition};
+                                                      outputState.usesClientComposition};
     base::unique_fd readyFence;
-
     if (!hasClientComposition) {
         return readyFence;
     }
 
     ALOGV("hasClientComposition");
 
-    auto& renderEngine = mCompositionEngine.getRenderEngine();
+    auto& renderEngine = getCompositionEngine().getRenderEngine();
     const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
 
     renderengine::DisplaySettings clientCompositionDisplay;
-    clientCompositionDisplay.physicalDisplay = mState.scissor;
-    clientCompositionDisplay.clip = mState.scissor;
-    clientCompositionDisplay.globalTransform = mState.transform.asMatrix4();
-    clientCompositionDisplay.orientation = mState.orientation;
-    clientCompositionDisplay.outputDataspace =
-            mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN;
+    clientCompositionDisplay.physicalDisplay = outputState.scissor;
+    clientCompositionDisplay.clip = outputState.scissor;
+    clientCompositionDisplay.globalTransform = outputState.transform.asMatrix4();
+    clientCompositionDisplay.orientation = outputState.orientation;
+    clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
+            ? outputState.dataspace
+            : ui::Dataspace::UNKNOWN;
     clientCompositionDisplay.maxLuminance =
             mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
 
     // Compute the global color transform matrix.
-    if (!mState.usesDeviceComposition && !getSkipColorTransform()) {
-        clientCompositionDisplay.colorTransform = mState.colorTransformMatrix;
+    if (!outputState.usesDeviceComposition && !getSkipColorTransform()) {
+        clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
     }
 
     // Note: Updated by generateClientCompositionRequests
@@ -833,7 +831,7 @@
     // If we the display is secure, protected content support is enabled, and at
     // least one layer has protected content, we need to use a secure back
     // buffer.
-    if (mState.isSecure && supportsProtectedContent) {
+    if (outputState.isSecure && supportsProtectedContent) {
         bool needsProtected =
                 std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
                             [](auto& layer) {
@@ -883,7 +881,8 @@
     std::vector<renderengine::LayerSettings> clientCompositionLayers;
     ALOGV("Rendering client layers");
 
-    const Region viewportRegion(mState.viewport);
+    const auto& outputState = getState();
+    const Region viewportRegion(outputState.viewport);
     const bool useIdentityTransform = false;
     bool firstLayer = true;
     // Used when a layer clears part of the buffer.
@@ -918,8 +917,8 @@
             compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
                     clip,
                     useIdentityTransform,
-                    layer->needsFiltering() || mState.needsFiltering,
-                    mState.isSecure,
+                    layer->needsFiltering() || outputState.needsFiltering,
+                    outputState.isSecure,
                     supportsProtectedContent,
                     clientComposition ? clearRegion : dummyRegion,
             };
@@ -972,14 +971,15 @@
         return;
     }
 
-    mState.dirtyRegion.clear();
+    auto& outputState = editState();
+    outputState.dirtyRegion.clear();
     mRenderSurface->flip();
 
     auto frame = presentAndGetFrameFences();
 
     mRenderSurface->onPresentDisplayCompleted();
 
-    for (auto& layer : getOutputLayersOrderedByZ()) {
+    for (auto& layer : mOutputLayersOrderedByZ) {
         // The layer buffer from the previous frame (if any) is released
         // by HWC only when the release fence from this frame (if any) is
         // signaled.  Always get the release fence from HWC first.
@@ -997,7 +997,7 @@
         // client target acquire fence when it is available, even though
         // this is suboptimal.
         // TODO(b/121291683): Track previous frame client target acquire fence.
-        if (mState.usesClientComposition) {
+        if (outputState.usesClientComposition) {
             releaseFence =
                     Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
         }
@@ -1006,7 +1006,7 @@
     }
 
     // We've got a list of layers needing fences, that are disjoint with
-    // getOutputLayersOrderedByZ.  The best we can do is to
+    // mOutputLayersOrderedByZ.  The best we can do is to
     // supply them with the present fence.
     for (auto& weakLayer : mReleasedLayers) {
         if (auto layer = weakLayer.promote(); layer != nullptr) {
@@ -1019,13 +1019,15 @@
 }
 
 void Output::dirtyEntireOutput() {
-    mState.dirtyRegion.set(mState.bounds);
+    auto& outputState = editState();
+    outputState.dirtyRegion.set(outputState.bounds);
 }
 
 void Output::chooseCompositionStrategy() {
     // The base output implementation can only do client composition
-    mState.usesClientComposition = true;
-    mState.usesDeviceComposition = false;
+    auto& outputState = editState();
+    outputState.usesClientComposition = true;
+    outputState.usesDeviceComposition = false;
 }
 
 bool Output::getSkipColorTransform() const {
@@ -1034,7 +1036,7 @@
 
 compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
     compositionengine::Output::FrameFences result;
-    if (mState.usesClientComposition) {
+    if (getState().usesClientComposition) {
         result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
     }
     return result;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 43ab87a..0124e5b 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -44,49 +44,26 @@
 
 } // namespace
 
-std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
+std::unique_ptr<OutputLayer> createOutputLayer(
         const compositionengine::Output& output,
         const std::shared_ptr<compositionengine::Layer>& layer,
         const sp<compositionengine::LayerFE>& layerFE) {
-    return std::make_unique<OutputLayer>(output, layer, layerFE);
+    return createOutputLayerTemplated<OutputLayer>(output, layer, layerFE);
 }
 
-OutputLayer::OutputLayer(const Output& output, const std::shared_ptr<Layer>& layer,
-                         const sp<LayerFE>& layerFE)
-      : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
-
 OutputLayer::~OutputLayer() = default;
 
 void OutputLayer::setHwcLayer(std::shared_ptr<HWC2::Layer> hwcLayer) {
+    auto& state = editState();
     if (hwcLayer) {
-        mState.hwc.emplace(hwcLayer);
+        state.hwc.emplace(std::move(hwcLayer));
     } else {
-        mState.hwc.reset();
+        state.hwc.reset();
     }
 }
 
-const compositionengine::Output& OutputLayer::getOutput() const {
-    return mOutput;
-}
-
-compositionengine::Layer& OutputLayer::getLayer() const {
-    return *mLayer;
-}
-
-compositionengine::LayerFE& OutputLayer::getLayerFE() const {
-    return *mLayerFE;
-}
-
-const OutputLayerCompositionState& OutputLayer::getState() const {
-    return mState;
-}
-
-OutputLayerCompositionState& OutputLayer::editState() {
-    return mState;
-}
-
 Rect OutputLayer::calculateInitialCrop() const {
-    const auto& layerState = mLayer->getFEState();
+    const auto& layerState = getLayer().getFEState();
 
     // apply the projection's clipping to the window crop in
     // layerstack space, and convert-back to layer space.
@@ -96,7 +73,7 @@
     FloatRect activeCropFloat =
             reduce(layerState.geomLayerBounds, layerState.transparentRegionHint);
 
-    const Rect& viewport = mOutput.getState().viewport;
+    const Rect& viewport = getOutput().getState().viewport;
     const ui::Transform& layerTransform = layerState.geomLayerTransform;
     const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
     // Transform to screen space.
@@ -119,8 +96,8 @@
 }
 
 FloatRect OutputLayer::calculateOutputSourceCrop() const {
-    const auto& layerState = mLayer->getFEState();
-    const auto& outputState = mOutput.getState();
+    const auto& layerState = getLayer().getFEState();
+    const auto& outputState = getOutput().getState();
 
     if (!layerState.geomUsesSourceCrop) {
         return {};
@@ -196,8 +173,8 @@
 }
 
 Rect OutputLayer::calculateOutputDisplayFrame() const {
-    const auto& layerState = mLayer->getFEState();
-    const auto& outputState = mOutput.getState();
+    const auto& layerState = getLayer().getFEState();
+    const auto& outputState = getOutput().getState();
 
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
@@ -243,8 +220,8 @@
 }
 
 uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const {
-    const auto& layerState = mLayer->getFEState();
-    const auto& outputState = mOutput.getState();
+    const auto& layerState = getLayer().getFEState();
+    const auto& outputState = getOutput().getState();
 
     /*
      * Transformations are applied in this order:
@@ -283,9 +260,10 @@
 } // namespace impl
 
 void OutputLayer::updateCompositionState(bool includeGeometry) {
-    const auto& layerFEState = mLayer->getFEState();
-    const auto& outputState = mOutput.getState();
-    const auto& profile = *mOutput.getDisplayColorProfile();
+    const auto& layerFEState = getLayer().getFEState();
+    const auto& outputState = getOutput().getState();
+    const auto& profile = *getOutput().getDisplayColorProfile();
+    auto& state = editState();
 
     if (includeGeometry) {
         // Clear the forceClientComposition flag before it is set for any
@@ -293,48 +271,49 @@
         // updating the geometry state, we only clear it when updating the
         // geometry since those conditions for forcing client composition won't
         // go away otherwise.
-        mState.forceClientComposition = false;
+        state.forceClientComposition = false;
 
-        mState.displayFrame = calculateOutputDisplayFrame();
-        mState.sourceCrop = calculateOutputSourceCrop();
-        mState.bufferTransform =
+        state.displayFrame = calculateOutputDisplayFrame();
+        state.sourceCrop = calculateOutputSourceCrop();
+        state.bufferTransform =
                 static_cast<Hwc2::Transform>(calculateOutputRelativeBufferTransform());
 
         if ((layerFEState.isSecure && !outputState.isSecure) ||
-            (mState.bufferTransform & ui::Transform::ROT_INVALID)) {
-            mState.forceClientComposition = true;
+            (state.bufferTransform & ui::Transform::ROT_INVALID)) {
+            state.forceClientComposition = true;
         }
     }
 
     // Determine the output dependent dataspace for this layer. If it is
     // colorspace agnostic, it just uses the dataspace chosen for the output to
     // avoid the need for color conversion.
-    mState.dataspace = layerFEState.isColorspaceAgnostic &&
+    state.dataspace = layerFEState.isColorspaceAgnostic &&
                     outputState.targetDataspace != ui::Dataspace::UNKNOWN
             ? outputState.targetDataspace
             : layerFEState.dataspace;
 
     // These are evaluated every frame as they can potentially change at any
     // time.
-    if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) {
-        mState.forceClientComposition = true;
+    if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(state.dataspace)) {
+        state.forceClientComposition = true;
     }
 }
 
 void OutputLayer::writeStateToHWC(bool includeGeometry) {
+    const auto& state = getState();
     // Skip doing this if there is no HWC interface
-    if (!mState.hwc) {
+    if (!state.hwc) {
         return;
     }
 
-    auto& hwcLayer = (*mState.hwc).hwcLayer;
+    auto& hwcLayer = (*state.hwc).hwcLayer;
     if (!hwcLayer) {
         ALOGE("[%s] failed to write composition state to HWC -- no hwcLayer for output %s",
-              mLayerFE->getDebugName(), mOutput.getName().c_str());
+              getLayerFE().getDebugName(), getOutput().getName().c_str());
         return;
     }
 
-    const auto& outputIndependentState = mLayer->getFEState();
+    const auto& outputIndependentState = getLayer().getFEState();
     auto requestedCompositionType = outputIndependentState.compositionType;
 
     if (includeGeometry) {
@@ -355,7 +334,7 @@
     if (auto error = hwcLayer->setDisplayFrame(outputDependentState.displayFrame);
         error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
-              mLayerFE->getDebugName(), outputDependentState.displayFrame.left,
+              getLayerFE().getDebugName(), outputDependentState.displayFrame.left,
               outputDependentState.displayFrame.top, outputDependentState.displayFrame.right,
               outputDependentState.displayFrame.bottom, to_string(error).c_str(),
               static_cast<int32_t>(error));
@@ -365,15 +344,15 @@
         error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
               "%s (%d)",
-              mLayerFE->getDebugName(), outputDependentState.sourceCrop.left,
+              getLayerFE().getDebugName(), outputDependentState.sourceCrop.left,
               outputDependentState.sourceCrop.top, outputDependentState.sourceCrop.right,
               outputDependentState.sourceCrop.bottom, to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
 
     if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), outputDependentState.z,
-              to_string(error).c_str(), static_cast<int32_t>(error));
+        ALOGE("[%s] Failed to set Z %u: %s (%d)", getLayerFE().getDebugName(),
+              outputDependentState.z, to_string(error).c_str(), static_cast<int32_t>(error));
     }
 
     // Solid-color layers should always use an identity transform.
@@ -383,7 +362,7 @@
             : static_cast<Hwc2::Transform>(0);
     if (auto error = hwcLayer->setTransform(static_cast<HWC2::Transform>(bufferTransform));
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set transform %s: %s (%d)", getLayerFE().getDebugName(),
               toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
@@ -394,21 +373,21 @@
     if (auto error = hwcLayer->setBlendMode(
                 static_cast<HWC2::BlendMode>(outputIndependentState.blendMode));
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set blend mode %s: %s (%d)", getLayerFE().getDebugName(),
               toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
 
     if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha);
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", getLayerFE().getDebugName(),
               outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error));
     }
 
     if (auto error = hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId);
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(),
-              static_cast<int32_t>(error));
+        ALOGE("[%s] Failed to set info %s (%d)", getLayerFE().getDebugName(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
     }
 }
 
@@ -419,14 +398,14 @@
     // state and should not change every frame.
     if (auto error = hwcLayer->setVisibleRegion(outputDependentState.outputSpaceVisibleRegion);
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set visible region: %s (%d)", getLayerFE().getDebugName(),
               to_string(error).c_str(), static_cast<int32_t>(error));
         outputDependentState.outputSpaceVisibleRegion.dump(LOG_TAG);
     }
 
     if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace);
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set dataspace %d: %s (%d)", getLayerFE().getDebugName(),
               outputDependentState.dataspace, to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
@@ -441,13 +420,13 @@
             editState().forceClientComposition = true;
             break;
         default:
-            ALOGE("[%s] Failed to set color transform: %s (%d)", mLayerFE->getDebugName(),
+            ALOGE("[%s] Failed to set color transform: %s (%d)", getLayerFE().getDebugName(),
                   to_string(error).c_str(), static_cast<int32_t>(error));
     }
 
     if (auto error = hwcLayer->setSurfaceDamage(outputIndependentState.surfaceDamage);
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set surface damage: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set surface damage: %s (%d)", getLayerFE().getDebugName(),
               to_string(error).c_str(), static_cast<int32_t>(error));
         outputIndependentState.surfaceDamage.dump(LOG_TAG);
     }
@@ -479,7 +458,7 @@
                          255};
 
     if (auto error = hwcLayer->setColor(color); error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set color: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set color: %s (%d)", getLayerFE().getDebugName(),
               to_string(error).c_str(), static_cast<int32_t>(error));
     }
 }
@@ -488,7 +467,7 @@
                                           const LayerFECompositionState& outputIndependentState) {
     if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", getLayerFE().getDebugName(),
               outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
@@ -497,11 +476,11 @@
 void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
                                         const LayerFECompositionState& outputIndependentState) {
     auto supportedPerFrameMetadata =
-            mOutput.getDisplayColorProfile()->getSupportedPerFrameMetadata();
+            getOutput().getDisplayColorProfile()->getSupportedPerFrameMetadata();
     if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
                                                    outputIndependentState.hdrMetadata);
         error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
-        ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", getLayerFE().getDebugName(),
               to_string(error).c_str(), static_cast<int32_t>(error));
     }
 
@@ -515,7 +494,7 @@
 
     if (auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, outputIndependentState.acquireFence);
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set buffer %p: %s (%d)", mLayerFE->getDebugName(),
+        ALOGE("[%s] Failed to set buffer %p: %s (%d)", getLayerFE().getDebugName(),
               outputIndependentState.buffer->handle, to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
@@ -537,7 +516,7 @@
         if (auto error = hwcLayer->setCompositionType(
                     static_cast<HWC2::Composition>(requestedCompositionType));
             error != HWC2::Error::None) {
-            ALOGE("[%s] Failed to set composition type %s: %s (%d)", mLayerFE->getDebugName(),
+            ALOGE("[%s] Failed to set composition type %s: %s (%d)", getLayerFE().getDebugName(),
                   toString(requestedCompositionType).c_str(), to_string(error).c_str(),
                   static_cast<int32_t>(error));
         }
@@ -551,8 +530,8 @@
         return;
     }
 
-    const auto& layerFEState = mLayer->getFEState();
-    const auto& outputState = mOutput.getState();
+    const auto& layerFEState = getLayer().getFEState();
+    const auto& outputState = getOutput().getState();
 
     Rect frame = layerFEState.cursorFrame;
     frame.intersect(outputState.viewport, &frame);
@@ -560,23 +539,26 @@
 
     if (auto error = hwcLayer->setCursorPosition(position.left, position.top);
         error != HWC2::Error::None) {
-        ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)", mLayerFE->getDebugName(),
-              position.left, position.top, to_string(error).c_str(), static_cast<int32_t>(error));
+        ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)",
+              getLayerFE().getDebugName(), position.left, position.top, to_string(error).c_str(),
+              static_cast<int32_t>(error));
     }
 }
 
 HWC2::Layer* OutputLayer::getHwcLayer() const {
-    return mState.hwc ? mState.hwc->hwcLayer.get() : nullptr;
+    const auto& state = getState();
+    return state.hwc ? state.hwc->hwcLayer.get() : nullptr;
 }
 
 bool OutputLayer::requiresClientComposition() const {
-    return !mState.hwc ||
-            mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
+    const auto& state = getState();
+    return !state.hwc ||
+            state.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
 }
 
 bool OutputLayer::isHardwareCursor() const {
-    return mState.hwc &&
-            mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CURSOR;
+    const auto& state = getState();
+    return state.hwc && state.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CURSOR;
 }
 
 void OutputLayer::detectDisallowedCompositionTypeChange(
@@ -602,15 +584,16 @@
 
     if (!result) {
         ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
-              mLayerFE->getDebugName(), toString(from).c_str(), static_cast<int>(from),
+              getLayerFE().getDebugName(), toString(from).c_str(), static_cast<int>(from),
               toString(to).c_str(), static_cast<int>(to));
     }
 }
 
 void OutputLayer::applyDeviceCompositionTypeChange(
         Hwc2::IComposerClient::Composition compositionType) {
-    LOG_FATAL_IF(!mState.hwc);
-    auto& hwcState = *mState.hwc;
+    auto& state = editState();
+    LOG_FATAL_IF(!state.hwc);
+    auto& hwcState = *state.hwc;
 
     detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
 
@@ -618,25 +601,28 @@
 }
 
 void OutputLayer::prepareForDeviceLayerRequests() {
-    mState.clearClientTarget = false;
+    auto& state = editState();
+    state.clearClientTarget = false;
 }
 
 void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) {
+    auto& state = editState();
     switch (request) {
         case Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET:
-            mState.clearClientTarget = true;
+            state.clearClientTarget = true;
             break;
 
         default:
-            ALOGE("[%s] Unknown device layer request %s (%d)", mLayerFE->getDebugName(),
+            ALOGE("[%s] Unknown device layer request %s (%d)", getLayerFE().getDebugName(),
                   toString(request).c_str(), static_cast<int>(request));
             break;
     }
 }
 
 bool OutputLayer::needsFiltering() const {
-    const auto& displayFrame = mState.displayFrame;
-    const auto& sourceCrop = mState.sourceCrop;
+    const auto& state = getState();
+    const auto& displayFrame = state.displayFrame;
+    const auto& sourceCrop = state.sourceCrop;
     return sourceCrop.getHeight() != displayFrame.getHeight() ||
             sourceCrop.getWidth() != displayFrame.getWidth();
 }
@@ -644,9 +630,9 @@
 void OutputLayer::dump(std::string& out) const {
     using android::base::StringAppendF;
 
-    StringAppendF(&out, "  - Output Layer %p (Composition layer %p) (%s)\n", this, mLayer.get(),
-                  mLayerFE->getDebugName());
-    mState.dump(out);
+    StringAppendF(&out, "  - Output Layer %p (Composition layer %p) (%s)\n", this, &getLayer(),
+                  getLayerFE().getDebugName());
+    dumpState(out);
 }
 
 } // namespace impl
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 1ce6b4c..5ed21fc 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -43,12 +43,13 @@
 
 std::unique_ptr<compositionengine::RenderSurface> createRenderSurface(
         const compositionengine::CompositionEngine& compositionEngine,
-        compositionengine::Display& display, compositionengine::RenderSurfaceCreationArgs&& args) {
-    return std::make_unique<RenderSurface>(compositionEngine, display, std::move(args));
+        compositionengine::Display& display,
+        const compositionengine::RenderSurfaceCreationArgs& args) {
+    return std::make_unique<RenderSurface>(compositionEngine, display, args);
 }
 
 RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display& display,
-                             RenderSurfaceCreationArgs&& args)
+                             const RenderSurfaceCreationArgs& args)
       : mCompositionEngine(compositionEngine),
         mDisplay(display),
         mNativeWindow(args.nativeWindow),
@@ -156,7 +157,7 @@
     return mGraphicBuffer;
 }
 
-void RenderSurface::queueBuffer(base::unique_fd&& readyFence) {
+void RenderSurface::queueBuffer(base::unique_fd readyFence) {
     auto& state = mDisplay.getState();
 
     if (state.usesClientComposition || state.flipClientTarget) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 74b3ada..8401f08 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -58,7 +58,7 @@
         layers.emplace_back(mLayer1);
         layers.emplace_back(mLayer2);
         layers.emplace_back(mLayer3);
-        mDisplay.setOutputLayersOrderedByZ(std::move(layers));
+        mDisplay->setOutputLayersOrderedByZ(std::move(layers));
     }
 
     StrictMock<android::mock::HWComposer> mHwComposer;
@@ -71,11 +71,12 @@
     mock::OutputLayer* mLayer1 = new StrictMock<mock::OutputLayer>();
     mock::OutputLayer* mLayer2 = new StrictMock<mock::OutputLayer>();
     mock::OutputLayer* mLayer3 = new StrictMock<mock::OutputLayer>();
-    impl::Display mDisplay{mCompositionEngine,
-                           DisplayCreationArgsBuilder()
-                                   .setDisplayId(DEFAULT_DISPLAY_ID)
-                                   .setPowerAdvisor(&mPowerAdvisor)
-                                   .build()};
+    std::shared_ptr<impl::Display> mDisplay =
+            impl::createDisplay(mCompositionEngine,
+                                DisplayCreationArgsBuilder()
+                                        .setDisplayId(DEFAULT_DISPLAY_ID)
+                                        .setPowerAdvisor(&mPowerAdvisor)
+                                        .build());
 };
 
 /*
@@ -95,12 +96,10 @@
 
     {
         constexpr DisplayId display2 = DisplayId{546u};
-        auto display = impl::createDisplay(mCompositionEngine,
-                                           DisplayCreationArgsBuilder()
-                                                   .setIsSecure(true)
-                                                   .setDisplayId(display2)
-                                                   .build());
-        EXPECT_TRUE(display->isSecure());
+        auto display =
+                impl::createDisplay(mCompositionEngine,
+                                    DisplayCreationArgsBuilder().setDisplayId(display2).build());
+        EXPECT_FALSE(display->isSecure());
         EXPECT_FALSE(display->isVirtual());
         EXPECT_EQ(display2, display->getId());
     }
@@ -126,13 +125,13 @@
     // The first call to disconnect will disconnect the display with the HWC and
     // set mHwcId to -1.
     EXPECT_CALL(mHwComposer, disconnectDisplay(DEFAULT_DISPLAY_ID)).Times(1);
-    mDisplay.disconnect();
-    EXPECT_FALSE(mDisplay.getId());
+    mDisplay->disconnect();
+    EXPECT_FALSE(mDisplay->getId());
 
     // Subsequent calls will do nothing,
     EXPECT_CALL(mHwComposer, disconnectDisplay(DEFAULT_DISPLAY_ID)).Times(0);
-    mDisplay.disconnect();
-    EXPECT_FALSE(mDisplay.getId());
+    mDisplay->disconnect();
+    EXPECT_FALSE(mDisplay->getId());
 }
 
 /*
@@ -143,7 +142,7 @@
     // No change does nothing
     CompositionRefreshArgs refreshArgs;
     refreshArgs.colorTransformMatrix = std::nullopt;
-    mDisplay.setColorTransform(refreshArgs);
+    mDisplay->setColorTransform(refreshArgs);
 
     // Identity matrix sets an identity state value
     const mat4 kIdentity;
@@ -151,7 +150,7 @@
     EXPECT_CALL(mHwComposer, setColorTransform(DEFAULT_DISPLAY_ID, kIdentity)).Times(1);
 
     refreshArgs.colorTransformMatrix = kIdentity;
-    mDisplay.setColorTransform(refreshArgs);
+    mDisplay->setColorTransform(refreshArgs);
 
     // Non-identity matrix sets a non-identity state value
     const mat4 kNonIdentity = mat4() * 2;
@@ -159,7 +158,7 @@
     EXPECT_CALL(mHwComposer, setColorTransform(DEFAULT_DISPLAY_ID, kNonIdentity)).Times(1);
 
     refreshArgs.colorTransformMatrix = kNonIdentity;
-    mDisplay.setColorTransform(refreshArgs);
+    mDisplay->setColorTransform(refreshArgs);
 }
 
 /*
@@ -170,27 +169,27 @@
     using ColorProfile = Output::ColorProfile;
 
     mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
-    mDisplay.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
+    mDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
     mock::DisplayColorProfile* colorProfile = new StrictMock<mock::DisplayColorProfile>();
-    mDisplay.setDisplayColorProfileForTest(std::unique_ptr<DisplayColorProfile>(colorProfile));
+    mDisplay->setDisplayColorProfileForTest(std::unique_ptr<DisplayColorProfile>(colorProfile));
 
     EXPECT_CALL(*colorProfile, getTargetDataspace(_, _, _))
             .WillRepeatedly(Return(ui::Dataspace::UNKNOWN));
 
     // These values are expected to be the initial state.
-    ASSERT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode);
-    ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace);
-    ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent);
-    ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace);
+    ASSERT_EQ(ui::ColorMode::NATIVE, mDisplay->getState().colorMode);
+    ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay->getState().dataspace);
+    ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay->getState().renderIntent);
+    ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay->getState().targetDataspace);
 
-    // If the set values are unchanged, nothing happens
-    mDisplay.setColorProfile(ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
-                                          ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN});
+    // Otherwise if the values are unchanged, nothing happens
+    mDisplay->setColorProfile(ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
+                                           ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN});
 
-    EXPECT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode);
-    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace);
-    EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent);
-    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace);
+    EXPECT_EQ(ui::ColorMode::NATIVE, mDisplay->getState().colorMode);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay->getState().dataspace);
+    EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay->getState().renderIntent);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay->getState().targetDataspace);
 
     // Otherwise if the values are different, updates happen
     EXPECT_CALL(*renderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
@@ -199,24 +198,24 @@
                                    ui::RenderIntent::TONE_MAP_COLORIMETRIC))
             .Times(1);
 
-    mDisplay.setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
-                                          ui::RenderIntent::TONE_MAP_COLORIMETRIC,
-                                          ui::Dataspace::UNKNOWN});
+    mDisplay->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
+                                           ui::RenderIntent::TONE_MAP_COLORIMETRIC,
+                                           ui::Dataspace::UNKNOWN});
 
-    EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mDisplay.getState().colorMode);
-    EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mDisplay.getState().dataspace);
-    EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mDisplay.getState().renderIntent);
-    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace);
+    EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mDisplay->getState().colorMode);
+    EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mDisplay->getState().dataspace);
+    EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mDisplay->getState().renderIntent);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay->getState().targetDataspace);
 }
 
 TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) {
     using ColorProfile = Output::ColorProfile;
 
-    impl::Display virtualDisplay{mCompositionEngine,
-                                 DisplayCreationArgs{false, true, DEFAULT_DISPLAY_ID}};
+    std::shared_ptr<impl::Display> virtualDisplay{
+            impl::createDisplay(mCompositionEngine, DisplayCreationArgs{true, DEFAULT_DISPLAY_ID})};
 
     mock::DisplayColorProfile* colorProfile = new StrictMock<mock::DisplayColorProfile>();
-    virtualDisplay.setDisplayColorProfileForTest(
+    virtualDisplay->setDisplayColorProfileForTest(
             std::unique_ptr<DisplayColorProfile>(colorProfile));
 
     EXPECT_CALL(*colorProfile,
@@ -224,14 +223,14 @@
                                    ui::Dataspace::UNKNOWN))
             .WillOnce(Return(ui::Dataspace::UNKNOWN));
 
-    virtualDisplay.setColorProfile(
+    virtualDisplay->setColorProfile(
             ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
                          ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN});
 
-    EXPECT_EQ(ui::ColorMode::NATIVE, virtualDisplay.getState().colorMode);
-    EXPECT_EQ(ui::Dataspace::UNKNOWN, virtualDisplay.getState().dataspace);
-    EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, virtualDisplay.getState().renderIntent);
-    EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace);
+    EXPECT_EQ(ui::ColorMode::NATIVE, virtualDisplay->getState().colorMode);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, virtualDisplay->getState().dataspace);
+    EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, virtualDisplay->getState().renderIntent);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, virtualDisplay->getState().targetDataspace);
 }
 
 /*
@@ -239,11 +238,11 @@
  */
 
 TEST_F(DisplayTest, createDisplayColorProfileSetsDisplayColorProfile) {
-    EXPECT_TRUE(mDisplay.getDisplayColorProfile() == nullptr);
-    mDisplay.createDisplayColorProfile(
+    EXPECT_TRUE(mDisplay->getDisplayColorProfile() == nullptr);
+    mDisplay->createDisplayColorProfile(
             DisplayColorProfileCreationArgs{false, HdrCapabilities(), 0,
                                             DisplayColorProfileCreationArgs::HwcColorModes()});
-    EXPECT_TRUE(mDisplay.getDisplayColorProfile() != nullptr);
+    EXPECT_TRUE(mDisplay->getDisplayColorProfile() != nullptr);
 }
 
 /*
@@ -252,9 +251,9 @@
 
 TEST_F(DisplayTest, createRenderSurfaceSetsRenderSurface) {
     EXPECT_CALL(*mNativeWindow, disconnect(NATIVE_WINDOW_API_EGL)).WillRepeatedly(Return(NO_ERROR));
-    EXPECT_TRUE(mDisplay.getRenderSurface() == nullptr);
-    mDisplay.createRenderSurface(RenderSurfaceCreationArgs{640, 480, mNativeWindow, nullptr});
-    EXPECT_TRUE(mDisplay.getRenderSurface() != nullptr);
+    EXPECT_TRUE(mDisplay->getRenderSurface() == nullptr);
+    mDisplay->createRenderSurface(RenderSurfaceCreationArgs{640, 480, mNativeWindow, nullptr});
+    EXPECT_TRUE(mDisplay->getRenderSurface() != nullptr);
 }
 
 /*
@@ -268,7 +267,7 @@
 
     EXPECT_CALL(mHwComposer, createLayer(DEFAULT_DISPLAY_ID)).WillOnce(Return(&hwcLayer));
 
-    auto outputLayer = mDisplay.createOutputLayer(layer, layerFE);
+    auto outputLayer = mDisplay->createOutputLayer(layer, layerFE);
 
     EXPECT_EQ(&hwcLayer, outputLayer->getHwcLayer());
 
@@ -308,13 +307,13 @@
     {
         Output::ReleasedLayers releasedLayers;
         releasedLayers.emplace_back(layerXLayerFE);
-        mDisplay.setReleasedLayers(std::move(releasedLayers));
+        mDisplay->setReleasedLayers(std::move(releasedLayers));
     }
 
     CompositionRefreshArgs refreshArgs;
-    mDisplay.setReleasedLayers(refreshArgs);
+    mDisplay->setReleasedLayers(refreshArgs);
 
-    const auto& releasedLayers = mDisplay.getReleasedLayersForTest();
+    const auto& releasedLayers = mDisplay->getReleasedLayersForTest();
     ASSERT_EQ(1, releasedLayers.size());
 }
 
@@ -341,9 +340,9 @@
     refreshArgs.layersWithQueuedFrames.push_back(&layerXLayer);
     refreshArgs.layersWithQueuedFrames.push_back(nullptr);
 
-    mDisplay.setReleasedLayers(refreshArgs);
+    mDisplay->setReleasedLayers(refreshArgs);
 
-    const auto& releasedLayers = mDisplay.getReleasedLayersForTest();
+    const auto& releasedLayers = mDisplay->getReleasedLayersForTest();
     ASSERT_EQ(2, releasedLayers.size());
     ASSERT_EQ(layer1LayerFE.get(), releasedLayers[0].promote().get());
     ASSERT_EQ(layer2LayerFE.get(), releasedLayers[1].promote().get());
@@ -356,8 +355,8 @@
 struct DisplayChooseCompositionStrategyTest : public testing::Test {
     struct DisplayPartialMock : public impl::Display {
         DisplayPartialMock(const compositionengine::CompositionEngine& compositionEngine,
-                           compositionengine::DisplayCreationArgs&& args)
-              : impl::Display(compositionEngine, std::move(args)) {}
+                           const compositionengine::DisplayCreationArgs& args)
+              : impl::Display(args), mCompositionEngine(compositionEngine) {}
 
         // Sets up the helper functions called by chooseCompositionStrategy to
         // use a mock implementations.
@@ -366,6 +365,21 @@
         MOCK_METHOD1(applyChangedTypesToLayers, void(const impl::Display::ChangedTypes&));
         MOCK_METHOD1(applyDisplayRequests, void(const impl::Display::DisplayRequests&));
         MOCK_METHOD1(applyLayerRequestsToLayers, void(const impl::Display::LayerRequests&));
+
+        // compositionengine::Output overrides
+        const OutputCompositionState& getState() const override { return mState; }
+        OutputCompositionState& editState() override { return mState; }
+
+        // compositionengine::impl::Output overrides
+        const CompositionEngine& getCompositionEngine() const override {
+            return mCompositionEngine;
+        };
+
+        // These need implementations though are not expected to be called.
+        MOCK_CONST_METHOD1(dumpState, void(std::string&));
+
+        const compositionengine::CompositionEngine& mCompositionEngine;
+        impl::OutputCompositionState mState;
     };
 
     DisplayChooseCompositionStrategyTest() {
@@ -380,12 +394,13 @@
 };
 
 TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutIfNotAHwcDisplay) {
-    impl::Display nonHwcDisplay{mCompositionEngine, DisplayCreationArgsBuilder().build()};
-    EXPECT_FALSE(nonHwcDisplay.getId());
+    std::shared_ptr<impl::Display> nonHwcDisplay{
+            impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())};
+    EXPECT_FALSE(nonHwcDisplay->getId());
 
-    nonHwcDisplay.chooseCompositionStrategy();
+    nonHwcDisplay->chooseCompositionStrategy();
 
-    auto& state = nonHwcDisplay.getState();
+    auto& state = nonHwcDisplay->getState();
     EXPECT_TRUE(state.usesClientComposition);
     EXPECT_FALSE(state.usesDeviceComposition);
 }
@@ -466,7 +481,7 @@
                 hasDisplayCapability(std::make_optional(DEFAULT_DISPLAY_ID),
                                      HWC2::DisplayCapability::SkipClientColorTransform))
             .WillOnce(Return(true));
-    EXPECT_TRUE(mDisplay.getSkipColorTransform());
+    EXPECT_TRUE(mDisplay->getSkipColorTransform());
 }
 
 /*
@@ -478,14 +493,14 @@
     EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(false));
     EXPECT_CALL(*mLayer3, requiresClientComposition()).WillOnce(Return(false));
 
-    EXPECT_FALSE(mDisplay.anyLayersRequireClientComposition());
+    EXPECT_FALSE(mDisplay->anyLayersRequireClientComposition());
 }
 
 TEST_F(DisplayTest, anyLayersRequireClientCompositionReturnsTrue) {
     EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(false));
     EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(true));
 
-    EXPECT_TRUE(mDisplay.anyLayersRequireClientComposition());
+    EXPECT_TRUE(mDisplay->anyLayersRequireClientComposition());
 }
 
 /*
@@ -497,14 +512,14 @@
     EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(true));
     EXPECT_CALL(*mLayer3, requiresClientComposition()).WillOnce(Return(true));
 
-    EXPECT_TRUE(mDisplay.allLayersRequireClientComposition());
+    EXPECT_TRUE(mDisplay->allLayersRequireClientComposition());
 }
 
 TEST_F(DisplayTest, allLayersRequireClientCompositionReturnsFalse) {
     EXPECT_CALL(*mLayer1, requiresClientComposition()).WillOnce(Return(true));
     EXPECT_CALL(*mLayer2, requiresClientComposition()).WillOnce(Return(false));
 
-    EXPECT_FALSE(mDisplay.allLayersRequireClientComposition());
+    EXPECT_FALSE(mDisplay->allLayersRequireClientComposition());
 }
 
 /*
@@ -512,7 +527,7 @@
  */
 
 TEST_F(DisplayTest, applyChangedTypesToLayersTakesEarlyOutIfNoChangedLayers) {
-    mDisplay.applyChangedTypesToLayers(impl::Display::ChangedTypes());
+    mDisplay->applyChangedTypesToLayers(impl::Display::ChangedTypes());
 }
 
 TEST_F(DisplayTest, applyChangedTypesToLayersAppliesChanges) {
@@ -523,7 +538,7 @@
                 applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::DEVICE))
             .Times(1);
 
-    mDisplay.applyChangedTypesToLayers(impl::Display::ChangedTypes{
+    mDisplay->applyChangedTypesToLayers(impl::Display::ChangedTypes{
             {&mHWC2Layer1, HWC2::Composition::Client},
             {&mHWC2Layer2, HWC2::Composition::Device},
             {&mHWC2LayerUnknown, HWC2::Composition::SolidColor},
@@ -535,30 +550,30 @@
  */
 
 TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesNoRequests) {
-    mDisplay.applyDisplayRequests(static_cast<HWC2::DisplayRequest>(0));
+    mDisplay->applyDisplayRequests(static_cast<HWC2::DisplayRequest>(0));
 
-    auto& state = mDisplay.getState();
+    auto& state = mDisplay->getState();
     EXPECT_FALSE(state.flipClientTarget);
 }
 
 TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesFlipClientTarget) {
-    mDisplay.applyDisplayRequests(HWC2::DisplayRequest::FlipClientTarget);
+    mDisplay->applyDisplayRequests(HWC2::DisplayRequest::FlipClientTarget);
 
-    auto& state = mDisplay.getState();
+    auto& state = mDisplay->getState();
     EXPECT_TRUE(state.flipClientTarget);
 }
 
 TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesWriteClientTargetToOutput) {
-    mDisplay.applyDisplayRequests(HWC2::DisplayRequest::WriteClientTargetToOutput);
+    mDisplay->applyDisplayRequests(HWC2::DisplayRequest::WriteClientTargetToOutput);
 
-    auto& state = mDisplay.getState();
+    auto& state = mDisplay->getState();
     EXPECT_FALSE(state.flipClientTarget);
 }
 
 TEST_F(DisplayTest, applyDisplayRequestsToLayersHandlesAllRequestFlagsSet) {
-    mDisplay.applyDisplayRequests(static_cast<HWC2::DisplayRequest>(~0));
+    mDisplay->applyDisplayRequests(static_cast<HWC2::DisplayRequest>(~0));
 
-    auto& state = mDisplay.getState();
+    auto& state = mDisplay->getState();
     EXPECT_TRUE(state.flipClientTarget);
 }
 
@@ -571,7 +586,7 @@
     EXPECT_CALL(*mLayer2, prepareForDeviceLayerRequests()).Times(1);
     EXPECT_CALL(*mLayer3, prepareForDeviceLayerRequests()).Times(1);
 
-    mDisplay.applyLayerRequestsToLayers(impl::Display::LayerRequests());
+    mDisplay->applyLayerRequestsToLayers(impl::Display::LayerRequests());
 }
 
 TEST_F(DisplayTest, applyLayerRequestsToLayers2) {
@@ -583,7 +598,7 @@
                 applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest::CLEAR_CLIENT_TARGET))
             .Times(1);
 
-    mDisplay.applyLayerRequestsToLayers(impl::Display::LayerRequests{
+    mDisplay->applyLayerRequestsToLayers(impl::Display::LayerRequests{
             {&mHWC2Layer1, HWC2::LayerRequest::ClearClientTarget},
             {&mHWC2LayerUnknown, HWC2::LayerRequest::ClearClientTarget},
     });
@@ -617,7 +632,7 @@
             .WillOnce(Return(layer2Fence));
     EXPECT_CALL(mHwComposer, clearReleaseFences(DEFAULT_DISPLAY_ID)).Times(1);
 
-    auto result = mDisplay.presentAndGetFrameFences();
+    auto result = mDisplay->presentAndGetFrameFences();
 
     EXPECT_EQ(presentFence, result.presentFence);
 
@@ -634,10 +649,10 @@
 
 TEST_F(DisplayTest, setExpensiveRenderingExpectedForwardsToPowerAdvisor) {
     EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, true)).Times(1);
-    mDisplay.setExpensiveRenderingExpected(true);
+    mDisplay->setExpensiveRenderingExpected(true);
 
     EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, false)).Times(1);
-    mDisplay.setExpensiveRenderingExpected(false);
+    mDisplay->setExpensiveRenderingExpected(false);
 }
 
 /*
@@ -646,20 +661,20 @@
 
 TEST_F(DisplayTest, finishFrameDoesNotSkipCompositionIfNotDirtyOnHwcDisplay) {
     mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
-    mDisplay.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
+    mDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
 
     // We expect no calls to queueBuffer if composition was skipped.
     EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(1);
 
-    mDisplay.editState().isEnabled = true;
-    mDisplay.editState().usesClientComposition = false;
-    mDisplay.editState().viewport = Rect(0, 0, 1, 1);
-    mDisplay.editState().dirtyRegion = Region::INVALID_REGION;
+    mDisplay->editState().isEnabled = true;
+    mDisplay->editState().usesClientComposition = false;
+    mDisplay->editState().viewport = Rect(0, 0, 1, 1);
+    mDisplay->editState().dirtyRegion = Region::INVALID_REGION;
 
     CompositionRefreshArgs refreshArgs;
     refreshArgs.repaintEverything = false;
 
-    mDisplay.finishFrame(refreshArgs);
+    mDisplay->finishFrame(refreshArgs);
 }
 
 TEST_F(DisplayTest, finishFrameSkipsCompositionIfNotDirty) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp
index 26115a3..787f973 100644
--- a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp
@@ -17,6 +17,7 @@
 #include <gtest/gtest.h>
 
 #include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/impl/Layer.h>
 #include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/LayerFE.h>
@@ -26,13 +27,28 @@
 
 using testing::StrictMock;
 
-class LayerTest : public testing::Test {
-public:
+struct LayerTest : public testing::Test {
+    struct Layer final : public impl::Layer {
+        explicit Layer(const LayerCreationArgs& args) : mLayerFE(args.layerFE) {}
+        ~Layer() override = default;
+
+        // compositionengine::Layer overrides
+        sp<LayerFE> getLayerFE() const { return mLayerFE.promote(); }
+        const LayerFECompositionState& getFEState() const override { return mFrontEndState; }
+        LayerFECompositionState& editFEState() override { return mFrontEndState; }
+
+        // compositionengine::impl::Layer overrides
+        void dumpFEState(std::string& out) const override { mFrontEndState.dump(out); }
+
+        const wp<LayerFE> mLayerFE;
+        LayerFECompositionState mFrontEndState;
+    };
+
     ~LayerTest() override = default;
 
     StrictMock<mock::CompositionEngine> mCompositionEngine;
     sp<LayerFE> mLayerFE = new StrictMock<mock::LayerFE>();
-    impl::Layer mLayer{mCompositionEngine, LayerCreationArgs{mLayerFE}};
+    Layer mLayer{LayerCreationArgs{mLayerFE}};
 };
 
 /* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index a1c156a..0347f75 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <compositionengine/impl/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/DisplayColorProfile.h>
 #include <compositionengine/mock/Layer.h>
@@ -55,6 +56,29 @@
 }
 
 struct OutputLayerTest : public testing::Test {
+    struct OutputLayer final : public impl::OutputLayer {
+        OutputLayer(const compositionengine::Output& output,
+                    std::shared_ptr<compositionengine::Layer> layer,
+                    sp<compositionengine::LayerFE> layerFE)
+              : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
+        ~OutputLayer() override = default;
+
+        // compositionengine::OutputLayer overrides
+        const compositionengine::Output& getOutput() const override { return mOutput; }
+        compositionengine::Layer& getLayer() const override { return *mLayer; }
+        compositionengine::LayerFE& getLayerFE() const override { return *mLayerFE; }
+        const impl::OutputLayerCompositionState& getState() const override { return mState; }
+        impl::OutputLayerCompositionState& editState() override { return mState; }
+
+        // compositionengine::impl::OutputLayer overrides
+        void dumpState(std::string& out) const override { mState.dump(out); }
+
+        const compositionengine::Output& mOutput;
+        std::shared_ptr<compositionengine::Layer> mLayer;
+        sp<compositionengine::LayerFE> mLayerFE;
+        impl::OutputLayerCompositionState mState;
+    };
+
     OutputLayerTest() {
         EXPECT_CALL(*mLayerFE, getDebugName()).WillRepeatedly(Return("Test LayerFE"));
         EXPECT_CALL(mOutput, getName()).WillRepeatedly(ReturnRef(kOutputName));
@@ -68,7 +92,7 @@
             new StrictMock<compositionengine::mock::Layer>()};
     sp<compositionengine::mock::LayerFE> mLayerFE{
             new StrictMock<compositionengine::mock::LayerFE>()};
-    impl::OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE};
+    OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE};
 
     LayerFECompositionState mLayerFEState;
     impl::OutputCompositionState mOutputState;
@@ -413,11 +437,26 @@
     OutputLayerPartialMockForUpdateCompositionState(const compositionengine::Output& output,
                                                     std::shared_ptr<compositionengine::Layer> layer,
                                                     sp<compositionengine::LayerFE> layerFE)
-          : impl::OutputLayer(output, layer, layerFE) {}
+          : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
     // Mock everything called by updateCompositionState to simplify testing it.
     MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
     MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
     MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t());
+
+    // compositionengine::OutputLayer overrides
+    const compositionengine::Output& getOutput() const override { return mOutput; }
+    compositionengine::Layer& getLayer() const override { return *mLayer; }
+    compositionengine::LayerFE& getLayerFE() const override { return *mLayerFE; }
+    const impl::OutputLayerCompositionState& getState() const override { return mState; }
+    impl::OutputLayerCompositionState& editState() override { return mState; }
+
+    // These need implementations though are not expected to be called.
+    MOCK_CONST_METHOD1(dumpState, void(std::string&));
+
+    const compositionengine::Output& mOutput;
+    std::shared_ptr<compositionengine::Layer> mLayer;
+    sp<compositionengine::LayerFE> mLayerFE;
+    impl::OutputLayerCompositionState mState;
 };
 
 struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest {
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 70c343b..635d77b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -51,11 +51,11 @@
 
 struct OutputTest : public testing::Test {
     OutputTest() {
-        mOutput.setDisplayColorProfileForTest(
+        mOutput->setDisplayColorProfileForTest(
                 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
-        mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
+        mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
 
-        mOutput.editState().bounds = kDefaultDisplaySize;
+        mOutput->editState().bounds = kDefaultDisplaySize;
     }
 
     static const Rect kDefaultDisplaySize;
@@ -63,7 +63,7 @@
     StrictMock<mock::CompositionEngine> mCompositionEngine;
     mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
     mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
-    impl::Output mOutput{mCompositionEngine};
+    std::shared_ptr<impl::Output> mOutput = impl::createOutput(mCompositionEngine);
 };
 
 const Rect OutputTest::kDefaultDisplaySize{100, 200};
@@ -77,14 +77,14 @@
     EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
     EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
 
-    EXPECT_TRUE(mOutput.isValid());
+    EXPECT_TRUE(mOutput->isValid());
 
     // If we take away the required components, it is no longer valid.
-    mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
+    mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
 
     EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
 
-    EXPECT_FALSE(mOutput.isValid());
+    EXPECT_FALSE(mOutput->isValid());
 }
 
 /*
@@ -92,30 +92,30 @@
  */
 
 TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
-    mOutput.editState().isEnabled = true;
+    mOutput->editState().isEnabled = true;
 
-    mOutput.setCompositionEnabled(true);
+    mOutput->setCompositionEnabled(true);
 
-    EXPECT_TRUE(mOutput.getState().isEnabled);
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
+    EXPECT_TRUE(mOutput->getState().isEnabled);
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
 }
 
 TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
-    mOutput.editState().isEnabled = false;
+    mOutput->editState().isEnabled = false;
 
-    mOutput.setCompositionEnabled(true);
+    mOutput->setCompositionEnabled(true);
 
-    EXPECT_TRUE(mOutput.getState().isEnabled);
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+    EXPECT_TRUE(mOutput->getState().isEnabled);
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
 TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
-    mOutput.editState().isEnabled = true;
+    mOutput->editState().isEnabled = true;
 
-    mOutput.setCompositionEnabled(false);
+    mOutput->setCompositionEnabled(false);
 
-    EXPECT_FALSE(mOutput.getState().isEnabled);
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+    EXPECT_FALSE(mOutput->getState().isEnabled);
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
 /*
@@ -130,14 +130,14 @@
     const Rect scissor{9, 10, 11, 12};
     const bool needsFiltering = true;
 
-    mOutput.setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
+    mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
 
-    EXPECT_THAT(mOutput.getState().transform, TransformEq(transform));
-    EXPECT_EQ(orientation, mOutput.getState().orientation);
-    EXPECT_EQ(frame, mOutput.getState().frame);
-    EXPECT_EQ(viewport, mOutput.getState().viewport);
-    EXPECT_EQ(scissor, mOutput.getState().scissor);
-    EXPECT_EQ(needsFiltering, mOutput.getState().needsFiltering);
+    EXPECT_THAT(mOutput->getState().transform, TransformEq(transform));
+    EXPECT_EQ(orientation, mOutput->getState().orientation);
+    EXPECT_EQ(frame, mOutput->getState().frame);
+    EXPECT_EQ(viewport, mOutput->getState().viewport);
+    EXPECT_EQ(scissor, mOutput->getState().scissor);
+    EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
 }
 
 /*
@@ -150,11 +150,11 @@
     EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
     EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
 
-    mOutput.setBounds(displaySize);
+    mOutput->setBounds(displaySize);
 
-    EXPECT_EQ(Rect(displaySize), mOutput.getState().bounds);
+    EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
 
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
 }
 
 /*
@@ -163,12 +163,12 @@
 
 TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
     const uint32_t layerStack = 123u;
-    mOutput.setLayerStackFilter(layerStack, true);
+    mOutput->setLayerStackFilter(layerStack, true);
 
-    EXPECT_TRUE(mOutput.getState().layerStackInternal);
-    EXPECT_EQ(layerStack, mOutput.getState().layerStackId);
+    EXPECT_TRUE(mOutput->getState().layerStackInternal);
+    EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
 
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
 /*
@@ -176,84 +176,84 @@
  */
 
 TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
-    mOutput.editState().colorTransformMatrix = kIdentity;
+    mOutput->editState().colorTransformMatrix = kIdentity;
 
     // If no colorTransformMatrix is set the update should be skipped.
     CompositionRefreshArgs refreshArgs;
     refreshArgs.colorTransformMatrix = std::nullopt;
 
-    mOutput.setColorTransform(refreshArgs);
+    mOutput->setColorTransform(refreshArgs);
 
     // The internal state should be unchanged
-    EXPECT_EQ(kIdentity, mOutput.getState().colorTransformMatrix);
+    EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
 
     // No dirty region should be set
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
 }
 
 TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
-    mOutput.editState().colorTransformMatrix = kIdentity;
+    mOutput->editState().colorTransformMatrix = kIdentity;
 
     // Attempting to set the same colorTransformMatrix that is already set should
     // also skip the update.
     CompositionRefreshArgs refreshArgs;
     refreshArgs.colorTransformMatrix = kIdentity;
 
-    mOutput.setColorTransform(refreshArgs);
+    mOutput->setColorTransform(refreshArgs);
 
     // The internal state should be unchanged
-    EXPECT_EQ(kIdentity, mOutput.getState().colorTransformMatrix);
+    EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
 
     // No dirty region should be set
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
 }
 
 TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
-    mOutput.editState().colorTransformMatrix = kNonIdentityHalf;
+    mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
 
     // Setting a different colorTransformMatrix should perform the update.
     CompositionRefreshArgs refreshArgs;
     refreshArgs.colorTransformMatrix = kIdentity;
 
-    mOutput.setColorTransform(refreshArgs);
+    mOutput->setColorTransform(refreshArgs);
 
     // The internal state should have been updated
-    EXPECT_EQ(kIdentity, mOutput.getState().colorTransformMatrix);
+    EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
 
     // The dirtyRegion should be set to the full display size
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
 TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
-    mOutput.editState().colorTransformMatrix = kIdentity;
+    mOutput->editState().colorTransformMatrix = kIdentity;
 
     // Setting a different colorTransformMatrix should perform the update.
     CompositionRefreshArgs refreshArgs;
     refreshArgs.colorTransformMatrix = kNonIdentityHalf;
 
-    mOutput.setColorTransform(refreshArgs);
+    mOutput->setColorTransform(refreshArgs);
 
     // The internal state should have been updated
-    EXPECT_EQ(kNonIdentityHalf, mOutput.getState().colorTransformMatrix);
+    EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
 
     // The dirtyRegion should be set to the full display size
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
 TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
-    mOutput.editState().colorTransformMatrix = kNonIdentityHalf;
+    mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
 
     // Setting a different colorTransformMatrix should perform the update.
     CompositionRefreshArgs refreshArgs;
     refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
 
-    mOutput.setColorTransform(refreshArgs);
+    mOutput->setColorTransform(refreshArgs);
 
     // The internal state should have been updated
-    EXPECT_EQ(kNonIdentityQuarter, mOutput.getState().colorTransformMatrix);
+    EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
 
     // The dirtyRegion should be set to the full display size
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
 /*
@@ -269,16 +269,16 @@
             .WillOnce(Return(ui::Dataspace::UNKNOWN));
     EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
 
-    mOutput.setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
-                                         ui::RenderIntent::TONE_MAP_COLORIMETRIC,
-                                         ui::Dataspace::UNKNOWN});
+    mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
+                                          ui::RenderIntent::TONE_MAP_COLORIMETRIC,
+                                          ui::Dataspace::UNKNOWN});
 
-    EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput.getState().colorMode);
-    EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput.getState().dataspace);
-    EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput.getState().renderIntent);
-    EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput.getState().targetDataspace);
+    EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
+    EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
+    EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
+    EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
 
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
 }
 
 TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) {
@@ -289,16 +289,16 @@
                                    ui::Dataspace::UNKNOWN))
             .WillOnce(Return(ui::Dataspace::UNKNOWN));
 
-    mOutput.editState().colorMode = ui::ColorMode::DISPLAY_P3;
-    mOutput.editState().dataspace = ui::Dataspace::DISPLAY_P3;
-    mOutput.editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
-    mOutput.editState().targetDataspace = ui::Dataspace::UNKNOWN;
+    mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
+    mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
+    mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
+    mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
 
-    mOutput.setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
-                                         ui::RenderIntent::TONE_MAP_COLORIMETRIC,
-                                         ui::Dataspace::UNKNOWN});
+    mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
+                                          ui::RenderIntent::TONE_MAP_COLORIMETRIC,
+                                          ui::Dataspace::UNKNOWN});
 
-    EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
+    EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
 }
 
 /*
@@ -311,9 +311,9 @@
     mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
     EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
 
-    mOutput.setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
+    mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
 
-    EXPECT_EQ(Rect(newDisplaySize), mOutput.getState().bounds);
+    EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
 }
 
 /*
@@ -322,11 +322,11 @@
 
 TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
     const Rect viewport{100, 200};
-    mOutput.editState().viewport = viewport;
-    mOutput.editState().dirtyRegion.set(50, 300);
+    mOutput->editState().viewport = viewport;
+    mOutput->editState().dirtyRegion.set(50, 300);
 
     {
-        Region result = mOutput.getDirtyRegion(true);
+        Region result = mOutput->getDirtyRegion(true);
 
         EXPECT_THAT(result, RegionEq(Region(viewport)));
     }
@@ -334,11 +334,11 @@
 
 TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
     const Rect viewport{100, 200};
-    mOutput.editState().viewport = viewport;
-    mOutput.editState().dirtyRegion.set(50, 300);
+    mOutput->editState().viewport = viewport;
+    mOutput->editState().dirtyRegion.set(50, 300);
 
     {
-        Region result = mOutput.getDirtyRegion(false);
+        Region result = mOutput->getDirtyRegion(false);
 
         // The dirtyRegion should be clipped to the display bounds.
         EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
@@ -354,26 +354,26 @@
     const uint32_t layerStack2 = 456u;
 
     // If the output accepts layerStack1 and internal-only layers....
-    mOutput.setLayerStackFilter(layerStack1, true);
+    mOutput->setLayerStackFilter(layerStack1, true);
 
     // A layer with no layerStack does not belong to it, internal-only or not.
-    EXPECT_FALSE(mOutput.belongsInOutput(std::nullopt, false));
-    EXPECT_FALSE(mOutput.belongsInOutput(std::nullopt, true));
+    EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
+    EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
 
     // Any layer with layerStack1 belongs to it, internal-only or not.
-    EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, false));
-    EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, true));
-    EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, true));
-    EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, false));
+    EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
+    EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
+    EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
+    EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
 
     // If the output accepts layerStack21 but not internal-only layers...
-    mOutput.setLayerStackFilter(layerStack1, false);
+    mOutput->setLayerStackFilter(layerStack1, false);
 
     // Only non-internal layers with layerStack1 belong to it.
-    EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, false));
-    EXPECT_FALSE(mOutput.belongsInOutput(layerStack1, true));
-    EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, true));
-    EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, false));
+    EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
+    EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
+    EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
+    EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
 }
 
 TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
@@ -386,59 +386,59 @@
     const uint32_t layerStack2 = 456u;
 
     // If the output accepts layerStack1 and internal-only layers....
-    mOutput.setLayerStackFilter(layerStack1, true);
+    mOutput->setLayerStackFilter(layerStack1, true);
 
     // A null layer pointer does not belong to the output
-    EXPECT_FALSE(mOutput.belongsInOutput(nullptr));
+    EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
 
     // A layer with no layerStack does not belong to it, internal-only or not.
     layerFEState.layerStackId = std::nullopt;
     layerFEState.internalOnly = false;
-    EXPECT_FALSE(mOutput.belongsInOutput(&layer));
+    EXPECT_FALSE(mOutput->belongsInOutput(&layer));
 
     layerFEState.layerStackId = std::nullopt;
     layerFEState.internalOnly = true;
-    EXPECT_FALSE(mOutput.belongsInOutput(&layer));
+    EXPECT_FALSE(mOutput->belongsInOutput(&layer));
 
     // Any layer with layerStack1 belongs to it, internal-only or not.
     layerFEState.layerStackId = layerStack1;
     layerFEState.internalOnly = false;
-    EXPECT_TRUE(mOutput.belongsInOutput(&layer));
+    EXPECT_TRUE(mOutput->belongsInOutput(&layer));
 
     layerFEState.layerStackId = layerStack1;
     layerFEState.internalOnly = true;
-    EXPECT_TRUE(mOutput.belongsInOutput(&layer));
+    EXPECT_TRUE(mOutput->belongsInOutput(&layer));
 
     layerFEState.layerStackId = layerStack2;
     layerFEState.internalOnly = true;
-    EXPECT_FALSE(mOutput.belongsInOutput(&layer));
+    EXPECT_FALSE(mOutput->belongsInOutput(&layer));
 
     layerFEState.layerStackId = layerStack2;
     layerFEState.internalOnly = false;
-    EXPECT_FALSE(mOutput.belongsInOutput(&layer));
+    EXPECT_FALSE(mOutput->belongsInOutput(&layer));
 
     // If the output accepts layerStack1 but not internal-only layers...
-    mOutput.setLayerStackFilter(layerStack1, false);
+    mOutput->setLayerStackFilter(layerStack1, false);
 
     // A null layer pointer does not belong to the output
-    EXPECT_FALSE(mOutput.belongsInOutput(nullptr));
+    EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
 
     // Only non-internal layers with layerStack1 belong to it.
     layerFEState.layerStackId = layerStack1;
     layerFEState.internalOnly = false;
-    EXPECT_TRUE(mOutput.belongsInOutput(&layer));
+    EXPECT_TRUE(mOutput->belongsInOutput(&layer));
 
     layerFEState.layerStackId = layerStack1;
     layerFEState.internalOnly = true;
-    EXPECT_FALSE(mOutput.belongsInOutput(&layer));
+    EXPECT_FALSE(mOutput->belongsInOutput(&layer));
 
     layerFEState.layerStackId = layerStack2;
     layerFEState.internalOnly = true;
-    EXPECT_FALSE(mOutput.belongsInOutput(&layer));
+    EXPECT_FALSE(mOutput->belongsInOutput(&layer));
 
     layerFEState.layerStackId = layerStack2;
     layerFEState.internalOnly = false;
-    EXPECT_FALSE(mOutput.belongsInOutput(&layer));
+    EXPECT_FALSE(mOutput->belongsInOutput(&layer));
 }
 
 /*
@@ -453,71 +453,24 @@
     outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer1));
     outputLayers.emplace_back(nullptr);
     outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer2));
-    mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
+    mOutput->setOutputLayersOrderedByZ(std::move(outputLayers));
 
     StrictMock<mock::Layer> layer;
     StrictMock<mock::Layer> otherLayer;
 
     // If the input layer matches the first OutputLayer, it will be returned.
     EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
-    EXPECT_EQ(outputLayer1, mOutput.getOutputLayerForLayer(&layer));
+    EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
 
     // If the input layer matches the second OutputLayer, it will be returned.
     EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
     EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
-    EXPECT_EQ(outputLayer2, mOutput.getOutputLayerForLayer(&layer));
+    EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
 
     // If the input layer does not match an output layer, null will be returned.
     EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
     EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
-    EXPECT_EQ(nullptr, mOutput.getOutputLayerForLayer(&layer));
-}
-
-/*
- * Output::getOrCreateOutputLayer()
- */
-
-TEST_F(OutputTest, getOrCreateOutputLayerWorks) {
-    mock::OutputLayer* existingOutputLayer = new StrictMock<mock::OutputLayer>();
-
-    Output::OutputLayers outputLayers;
-    outputLayers.emplace_back(nullptr);
-    outputLayers.emplace_back(std::unique_ptr<OutputLayer>(existingOutputLayer));
-    mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
-
-    std::shared_ptr<mock::Layer> layer{new StrictMock<mock::Layer>()};
-    sp<LayerFE> layerFE{new StrictMock<mock::LayerFE>()};
-
-    StrictMock<mock::Layer> otherLayer;
-
-    {
-        // If there is no OutputLayer corresponding to the input layer, a
-        // new OutputLayer is constructed and returned.
-        EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(otherLayer));
-        auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
-        EXPECT_NE(existingOutputLayer, result.get());
-        EXPECT_TRUE(result.get() != nullptr);
-        EXPECT_EQ(layer.get(), &result->getLayer());
-        EXPECT_EQ(layerFE.get(), &result->getLayerFE());
-
-        // The entries in the ordered array should be unchanged.
-        auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
-        EXPECT_EQ(nullptr, outputLayers[0].get());
-        EXPECT_EQ(existingOutputLayer, outputLayers[1].get());
-    }
-
-    {
-        // If there is an existing OutputLayer for the requested layer, an owned
-        // pointer is returned
-        EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(*layer));
-        auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
-        EXPECT_EQ(existingOutputLayer, result.get());
-
-        // The corresponding entry in the ordered array should be cleared.
-        auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
-        EXPECT_EQ(nullptr, outputLayers[0].get());
-        EXPECT_EQ(nullptr, outputLayers[1].get());
-    }
+    EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
 }
 
 /*
@@ -526,12 +479,19 @@
 
 struct OutputPrepareFrameTest : public testing::Test {
     struct OutputPartialMock : public impl::Output {
-        OutputPartialMock(const compositionengine::CompositionEngine& compositionEngine)
-              : impl::Output(compositionEngine) {}
-
         // Sets up the helper functions called by prepareFrame to use a mock
         // implementations.
         MOCK_METHOD0(chooseCompositionStrategy, void());
+
+        // compositionengine::Output overrides
+        const OutputCompositionState& getState() const override { return mState; }
+        OutputCompositionState& editState() override { return mState; }
+
+        // These need implementations though are not expected to be called.
+        MOCK_CONST_METHOD1(dumpState, void(std::string&));
+        MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
+
+        impl::OutputCompositionState mState;
     };
 
     OutputPrepareFrameTest() {
@@ -543,7 +503,7 @@
     StrictMock<mock::CompositionEngine> mCompositionEngine;
     mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
     mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
-    StrictMock<OutputPartialMock> mOutput{mCompositionEngine};
+    StrictMock<OutputPartialMock> mOutput;
 };
 
 TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
@@ -566,16 +526,16 @@
 // Note: Use OutputTest and not OutputPrepareFrameTest, so the real
 // base chooseCompositionStrategy() is invoked.
 TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
-    mOutput.editState().isEnabled = true;
-    mOutput.editState().usesClientComposition = false;
-    mOutput.editState().usesDeviceComposition = true;
+    mOutput->editState().isEnabled = true;
+    mOutput->editState().usesClientComposition = false;
+    mOutput->editState().usesDeviceComposition = true;
 
     EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
 
-    mOutput.prepareFrame();
+    mOutput->prepareFrame();
 
-    EXPECT_TRUE(mOutput.getState().usesClientComposition);
-    EXPECT_FALSE(mOutput.getState().usesDeviceComposition);
+    EXPECT_TRUE(mOutput->getState().usesClientComposition);
+    EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
 }
 
 /*
@@ -592,9 +552,6 @@
     static const mat4 kDefaultColorTransformMat;
 
     struct OutputPartialMock : public impl::Output {
-        OutputPartialMock(const compositionengine::CompositionEngine& compositionEngine)
-              : impl::Output(compositionEngine) {}
-
         // Sets up the helper functions called by composeSurfaces to use a mock
         // implementations.
         MOCK_CONST_METHOD0(getSkipColorTransform, bool());
@@ -603,6 +560,16 @@
         MOCK_METHOD2(appendRegionFlashRequests,
                      void(const Region&, std::vector<renderengine::LayerSettings>&));
         MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
+
+        // compositionengine::Output overrides
+        const OutputCompositionState& getState() const override { return mState; }
+        OutputCompositionState& editState() override { return mState; }
+
+        // These need implementations though are not expected to be called.
+        MOCK_CONST_METHOD1(dumpState, void(std::string&));
+        MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
+
+        impl::OutputCompositionState mState;
     };
 
     OutputComposeSurfacesTest() {
@@ -627,6 +594,7 @@
         mOutput.editState().usesClientComposition = true;
         mOutput.editState().usesDeviceComposition = false;
 
+        EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
         EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
     }
 
@@ -636,7 +604,7 @@
     mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
     mock::OutputLayer* mOutputLayer1 = new StrictMock<mock::OutputLayer>();
     mock::OutputLayer* mOutputLayer2 = new StrictMock<mock::OutputLayer>();
-    StrictMock<OutputPartialMock> mOutput{mCompositionEngine};
+    StrictMock<OutputPartialMock> mOutput;
     sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
 };
 
@@ -691,14 +659,22 @@
 
 struct GenerateClientCompositionRequestsTest : public testing::Test {
     struct OutputPartialMock : public impl::Output {
-        OutputPartialMock(const compositionengine::CompositionEngine& compositionEngine)
-              : impl::Output(compositionEngine) {}
+        // compositionengine::Output overrides
 
         std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
                 bool supportsProtectedContent, Region& clearRegion) override {
             return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
                                                                    clearRegion);
         }
+
+        const OutputCompositionState& getState() const override { return mState; }
+        OutputCompositionState& editState() override { return mState; }
+
+        // These need implementations though are not expected to be called.
+        MOCK_CONST_METHOD1(dumpState, void(std::string&));
+        MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
+
+        impl::OutputCompositionState mState;
     };
 
     GenerateClientCompositionRequestsTest() {
@@ -707,10 +683,9 @@
         mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
     }
 
-    StrictMock<mock::CompositionEngine> mCompositionEngine;
     mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
     mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
-    StrictMock<OutputPartialMock> mOutput{mCompositionEngine};
+    StrictMock<OutputPartialMock> mOutput;
 };
 
 // TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 2ada86b..b1fcff2 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -59,12 +59,13 @@
         mSequenceId(args.sequenceId),
         mDisplayInstallOrientation(args.displayInstallOrientation),
         mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay(
-                compositionengine::DisplayCreationArgs{args.isSecure, args.isVirtual,
-                                                       args.displayId, args.powerAdvisor})},
+                compositionengine::DisplayCreationArgs{args.isVirtual, args.displayId,
+                                                       args.powerAdvisor})},
         mIsVirtual(args.isVirtual),
         mOrientation(),
         mActiveConfig(0),
         mIsPrimary(args.isPrimary) {
+    mCompositionDisplay->editState().isSecure = args.isSecure;
     mCompositionDisplay->createRenderSurface(
             compositionengine::RenderSurfaceCreationArgs{ANativeWindow_getWidth(
                                                                  args.nativeWindow.get()),