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/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) {