Merge "[Mirror Layers] Added clone function to layers (1/4)"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 86558ef..d9c9e4a 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1057,7 +1057,7 @@
         std::string path(title);
         path.append(" - ").append(String8(service).c_str());
         size_t bytes_written = 0;
-        status_t status = dumpsys.startDumpThread(service, args);
+        status_t status = dumpsys.startDumpThread(service, /* dumpPid = */ true,  args);
         if (status == OK) {
             dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
             std::chrono::duration<double> elapsed_seconds;
@@ -1129,7 +1129,7 @@
             path.append("_HIGH");
         }
         path.append(kProtoExt);
-        status_t status = dumpsys.startDumpThread(service, args);
+        status_t status = dumpsys.startDumpThread(service, /* dumpPid = */ false, args);
         if (status == OK) {
             status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
             bool dumpTerminated = (status == OK);
@@ -2708,7 +2708,7 @@
     }
 
     /* tell activity manager we're done */
-    if (options_->do_broadcast) {
+    if (options_->do_broadcast && !CalledByApi()) {
         SendBugreportFinishedBroadcast();
         // Note that listener_ is notified in Run();
     }
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 4811927..68b3907 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -236,11 +236,13 @@
         return 0;
     }
 
+    const bool dumpPid = !asProto;
+
     for (size_t i = 0; i < N; i++) {
         const String16& serviceName = services[i];
         if (IsSkipped(skippedServices, serviceName)) continue;
 
-        if (startDumpThread(serviceName, args) == OK) {
+        if (startDumpThread(serviceName, dumpPid, args) == OK) {
             bool addSeparator = (N > 1);
             if (addSeparator) {
                 writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
@@ -307,7 +309,7 @@
     }
 }
 
-status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<String16>& args) {
+status_t Dumpsys::startDumpThread(const String16& serviceName, bool dumpPid, const Vector<String16>& args) {
     sp<IBinder> service = sm_->checkService(serviceName);
     if (service == nullptr) {
         aerr << "Can't find service: " << serviceName << endl;
@@ -327,7 +329,20 @@
 
     // dump blocks until completion, so spawn a thread..
     activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
-        int err = service->dump(remote_end.get(), args);
+        if (dumpPid) {
+            pid_t pid;
+            status_t status = service->getDebugPid(&pid);
+            if (status == OK) {
+                std::ostringstream pidinfo;
+                pidinfo << "Pid: " << pid << std::endl;
+                WriteStringToFd(pidinfo.str(), remote_end.get());
+            } else {
+                aerr << "Error getting pid status_t (" << status << "): "
+                        << serviceName << endl;
+            }
+        }
+
+        status_t err = service->dump(remote_end.get(), args);
 
         // It'd be nice to be able to close the remote end of the socketpair before the dump
         // call returns, to terminate our reads if the other end closes their copy of the
@@ -335,8 +350,8 @@
         // way to do this, though.
         remote_end.reset();
 
-        if (err != 0) {
-            aerr << "Error dumping service info: (" << strerror(err) << ") "
+        if (err != OK) {
+            aerr << "Error dumping service info status_t (" << err << "): "
                  << serviceName << endl;
         }
     });
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index c48a1e9..8d1291a 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -56,12 +56,13 @@
      * the output to a pipe. Thread must be stopped by a subsequent callto {@code
      * stopDumpThread}.
      * @param serviceName
+     * @param dumpPid whether to include a header with service PID information
      * @param args list of arguments to pass to service dump method.
      * @return {@code OK} thread is started successfully.
      *         {@code NAME_NOT_FOUND} service could not be found.
      *         {@code != OK} error
      */
-    status_t startDumpThread(const String16& serviceName, const Vector<String16>& args);
+    status_t startDumpThread(const String16& serviceName, bool dumpPid, const Vector<String16>& args);
 
     /**
      * Writes a section header to a file descriptor.
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index cbac839..d0b167e 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -188,22 +188,6 @@
         EXPECT_THAT(status, Eq(0));
     }
 
-    void CallSingleService(const String16& serviceName, Vector<String16>& args, int priorityFlags,
-                           bool supportsProto, std::chrono::duration<double>& elapsedDuration,
-                           size_t& bytesWritten) {
-        CaptureStdout();
-        CaptureStderr();
-        dump_.setServiceArgs(args, supportsProto, priorityFlags);
-        status_t status = dump_.startDumpThread(serviceName, args);
-        EXPECT_THAT(status, Eq(0));
-        status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false,
-                                 elapsedDuration, bytesWritten);
-        EXPECT_THAT(status, Eq(0));
-        dump_.stopDumpThread(/* dumpCompleted = */ true);
-        stdout_ = GetCapturedStdout();
-        stderr_ = GetCapturedStderr();
-    }
-
     void AssertRunningServices(const std::vector<std::string>& services) {
         std::string expected;
         if (services.size() > 1) {
@@ -215,16 +199,13 @@
         EXPECT_THAT(stdout_, HasSubstr(expected));
     }
 
-    void AssertOutput(const std::string& expected) {
-        EXPECT_THAT(stdout_, StrEq(expected));
-    }
-
     void AssertOutputContains(const std::string& expected) {
         EXPECT_THAT(stdout_, HasSubstr(expected));
     }
 
     void AssertDumped(const std::string& service, const std::string& dump) {
-        EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump));
+        EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n"));
+        EXPECT_THAT(stdout_, HasSubstr(dump));
         EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: "));
     }
 
@@ -232,7 +213,8 @@
                                   const char16_t* priorityType) {
         std::string priority = String8(priorityType).c_str();
         EXPECT_THAT(stdout_,
-                    HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n" + dump));
+                    HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n"));
+        EXPECT_THAT(stdout_, HasSubstr(dump));
         EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: "));
     }
 
@@ -313,7 +295,8 @@
 
     CallMain({"Valet"});
 
-    AssertOutput("Here's your car");
+    AssertOutputContains("Pid: " + std::to_string(getpid()));
+    AssertOutputContains("Here's your car");
 }
 
 // Tests 'dumpsys -t 1 service_name' on a service that times out after 2s
@@ -348,7 +331,7 @@
 
     CallMain({"SERVICE", "Y", "U", "NO", "HANDLE", "ARGS"});
 
-    AssertOutput("I DO!");
+    AssertOutputContains("I DO!");
 }
 
 // Tests dumpsys passes the -a flag when called on all services
@@ -539,23 +522,6 @@
     AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
 }
 
-TEST_F(DumpsysTest, GetBytesWritten) {
-    const char* serviceName = "service2";
-    const char* dumpContents = "dump1";
-    ExpectDump(serviceName, dumpContents);
-
-    String16 service(serviceName);
-    Vector<String16> args;
-    std::chrono::duration<double> elapsedDuration;
-    size_t bytesWritten;
-
-    CallSingleService(service, args, IServiceManager::DUMP_FLAG_PRIORITY_ALL,
-                      /* as_proto = */ false, elapsedDuration, bytesWritten);
-
-    AssertOutput(dumpContents);
-    EXPECT_THAT(bytesWritten, Eq(strlen(dumpContents)));
-}
-
 TEST_F(DumpsysTest, WriteDumpWithoutThreadStart) {
     std::chrono::duration<double> elapsedDuration;
     size_t bytesWritten;
@@ -563,4 +529,4 @@
         dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500),
                         /* as_proto = */ false, elapsedDuration, bytesWritten);
     EXPECT_THAT(status, Eq(INVALID_OPERATION));
-}
\ No newline at end of file
+}
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index 6fba0ac..01cf2f8 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -64,6 +64,20 @@
     ANDROID_BITMAP_FORMAT_RGBA_F16  = 9,
 };
 
+/** Bitmap alpha format */
+enum {
+    /** Pixel components are premultiplied by alpha. */
+    ANDROID_BITMAP_FLAGS_ALPHA_PREMUL   = 0,
+    /** Pixels are opaque. */
+    ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE   = 1,
+    /** Pixel components are independent of alpha. */
+    ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL = 2,
+    /** Bit mask for AndroidBitmapFormat.flags to isolate the alpha. */
+    ANDROID_BITMAP_FLAGS_ALPHA_MASK     = 0x3,
+    /** Shift for AndroidBitmapFormat.flags to isolate the alpha. */
+    ANDROID_BITMAP_FLAGS_ALPHA_SHIFT    = 0,
+};
+
 /** Bitmap info, see AndroidBitmap_getInfo(). */
 typedef struct {
     /** The bitmap width in pixels. */
@@ -74,8 +88,9 @@
     uint32_t    stride;
     /** The bitmap pixel format. See {@link AndroidBitmapFormat} */
     int32_t     format;
-    /** Unused. */
-    uint32_t    flags;      // 0 for now
+    /** Two bits are used to encode alpha. Use ANDROID_BITMAP_FLAGS_ALPHA_MASK
+      * and ANDROID_BITMAP_FLAGS_ALPHA_SHIFT to retrieve them. */
+    uint32_t    flags;
 } AndroidBitmapInfo;
 
 /**
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 28b8d80..c056c97 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -35,7 +35,6 @@
 
 #include <binder/IBinder.h>
 #include <input/Input.h>
-#include <input/LatencyStatistics.h>
 #include <utils/BitSet.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -289,12 +288,8 @@
     status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);
 
 private:
-    static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min;
 
     sp<InputChannel> mChannel;
-    LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD};
-
-    void reportTouchEventForStatistics(nsecs_t evdevTime);
 };
 
 /*
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 693045e..34b6ea5 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -99,6 +99,32 @@
     return reply.readNullableStrongBinder(out);
 }
 
+status_t IBinder::getDebugPid(pid_t* out) {
+    BBinder* local = this->localBinder();
+    if (local != nullptr) {
+      *out = local->getDebugPid();
+      return OK;
+    }
+
+    BpBinder* proxy = this->remoteBinder();
+    LOG_ALWAYS_FATAL_IF(proxy == nullptr);
+
+    Parcel data;
+    Parcel reply;
+    status_t status = transact(DEBUG_PID_TRANSACTION, data, &reply);
+    if (status != OK) return status;
+
+    int32_t pid;
+    status = reply.readInt32(&pid);
+    if (status != OK) return status;
+
+    if (pid < 0 || pid > std::numeric_limits<pid_t>::max()) {
+        return BAD_VALUE;
+    }
+    *out = pid;
+    return OK;
+}
+
 // ---------------------------------------------------------------------------
 
 class BBinder::Extras
@@ -152,6 +178,9 @@
         case EXTENSION_TRANSACTION:
             err = reply->writeStrongBinder(getExtension());
             break;
+        case DEBUG_PID_TRANSACTION:
+            err = reply->writeInt32(getDebugPid());
+            break;
         default:
             err = onTransact(code, data, reply, flags);
             break;
@@ -250,6 +279,10 @@
     return e->mExtension;
 }
 
+pid_t BBinder::getDebugPid() {
+    return getpid();
+}
+
 void BBinder::setExtension(const sp<IBinder>& extension) {
     Extras* e = getOrCreateExtras();
     e->mExtension = extension;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 7c45c77..c666097 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -597,9 +597,8 @@
         result = getAndExecuteCommand();
 
         if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
-            ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
+            LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                   mProcess->mDriverFD, result);
-            abort();
         }
 
         // Let this thread exit the thread pool if it is no longer
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2a75619..36dc810 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -68,7 +68,7 @@
 
 static size_t pad_size(size_t s) {
     if (s > (std::numeric_limits<size_t>::max() - 3)) {
-        abort();
+        LOG_ALWAYS_FATAL("pad size too big %zu", s);
     }
     return PAD_SIZE_UNSAFE(s);
 }
@@ -295,7 +295,7 @@
 {
     size_t result = dataSize() - dataPosition();
     if (result > INT32_MAX) {
-        abort();
+        LOG_ALWAYS_FATAL("result too big: %zu", result);
     }
     return result;
 }
@@ -332,7 +332,7 @@
     if (pos > INT32_MAX) {
         // don't accept size_t values which may have come from an
         // inadvertent conversion from a negative int.
-        abort();
+        LOG_ALWAYS_FATAL("pos too big: %zu", pos);
     }
 
     mDataPos = pos;
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 1095c7f..5673d5a 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -68,6 +68,8 @@
     // This must be called before the object is sent to another process. Not thread safe.
     void                setExtension(const sp<IBinder>& extension);
 
+    pid_t               getDebugPid();
+
 protected:
     virtual             ~BBinder();
 
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 027e088..b127234 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -59,6 +59,7 @@
         INTERFACE_TRANSACTION   = B_PACK_CHARS('_', 'N', 'T', 'F'),
         SYSPROPS_TRANSACTION    = B_PACK_CHARS('_', 'S', 'P', 'R'),
         EXTENSION_TRANSACTION   = B_PACK_CHARS('_', 'E', 'X', 'T'),
+        DEBUG_PID_TRANSACTION   = B_PACK_CHARS('_', 'P', 'I', 'D'),
 
         // Corresponds to TF_ONE_WAY -- an asynchronous call.
         FLAG_ONEWAY             = 0x00000001
@@ -129,6 +130,11 @@
      */
     status_t                getExtension(sp<IBinder>* out);
 
+    /**
+     * Dump PID for a binder, for debugging.
+     */
+    status_t                getDebugPid(pid_t* outPid);
+
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t        transact(   uint32_t code,
                                         const Parcel& data,
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 7749e66..8efaf3d 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -57,7 +57,6 @@
                 "libutils",
                 "libbinder",
                 "libui",
-                "libstatslog",
             ],
 
             sanitize: {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 8a2fc2a..366c93c 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -34,7 +34,6 @@
 #include <utils/Trace.h>
 
 #include <input/InputTransport.h>
-#include <statslog.h>
 
 using android::base::StringPrintf;
 
@@ -538,9 +537,6 @@
         msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]);
     }
 
-    if (source == AINPUT_SOURCE_TOUCHSCREEN) {
-        reportTouchEventForStatistics(eventTime);
-    }
     return mChannel->sendMessage(&msg);
 }
 
@@ -567,17 +563,6 @@
     return OK;
 }
 
-void InputPublisher::reportTouchEventForStatistics(nsecs_t evdevTime) {
-    if (mTouchStatistics.shouldReport()) {
-        android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(),
-                                   mTouchStatistics.getMax(), mTouchStatistics.getMean(),
-                                   mTouchStatistics.getStDev(), mTouchStatistics.getCount());
-        mTouchStatistics.reset();
-    }
-    nsecs_t latency = nanoseconds_to_microseconds(systemTime(CLOCK_MONOTONIC) - evdevTime);
-    mTouchStatistics.addValue(latency);
-}
-
 // --- InputConsumer ---
 
 InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
diff --git a/libs/input/LatencyStatistics.cpp b/libs/input/LatencyStatistics.cpp
index e343578..394da22 100644
--- a/libs/input/LatencyStatistics.cpp
+++ b/libs/input/LatencyStatistics.cpp
@@ -84,7 +84,7 @@
 
 bool LatencyStatistics::shouldReport() {
     std::chrono::duration timeSinceReport = std::chrono::steady_clock::now() - mLastReportTime;
-    return mCount != 0 && timeSinceReport > mReportPeriod;
+    return mCount != 0 && timeSinceReport >= mReportPeriod;
 }
 
 } // namespace android
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 11578c3..f6b5935 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -44,6 +44,7 @@
         "libhidlbase",
         "libinput",
         "liblog",
+        "libstatslog",
         "libutils",
         "libui",
         "server_configurable_flags",
diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp
index bc53cf5..0422d83 100644
--- a/services/inputflinger/InputReaderBase.cpp
+++ b/services/inputflinger/InputReaderBase.cpp
@@ -114,8 +114,10 @@
     std::optional<DisplayViewport> result = std::nullopt;
     for (const DisplayViewport& currentViewport : mDisplays) {
         // Return the first match
-        if (currentViewport.type == type && !result) {
-            result = std::make_optional(currentViewport);
+        if (currentViewport.type == type) {
+            if (!result) {
+                result = std::make_optional(currentViewport);
+            }
             count++;
         }
     }
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index b8c3a80..9185e00 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -34,6 +34,7 @@
         "libinputreporter",
         "libinputflinger_base",
         "liblog",
+        "libstatslog",
         "libui",
         "libutils",
     ],
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index a9e22f1..28c2799 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -29,6 +29,9 @@
 
 namespace android::inputdispatcher {
 
+// Sequence number for synthesized or injected events.
+constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
+
 struct EventEntry {
     enum { TYPE_CONFIGURATION_CHANGED, TYPE_DEVICE_RESET, TYPE_KEY, TYPE_MOTION };
 
@@ -41,8 +44,23 @@
 
     bool dispatchInProgress; // initially false, set to true while dispatching
 
+    /**
+     * Injected keys are events from an external (probably untrusted) application
+     * and are not related to real hardware state. They come in via
+     * InputDispatcher::injectInputEvent, which sets policy flag POLICY_FLAG_INJECTED.
+     */
     inline bool isInjected() const { return injectionState != nullptr; }
 
+    /**
+     * Synthesized events are either injected events, or events that come
+     * from real hardware, but aren't directly attributable to a specific hardware event.
+     * Key repeat is a synthesized event, because it is related to an actual hardware state
+     * (a key is currently pressed), but the repeat itself is generated by the framework.
+     */
+    inline bool isSynthesized() const {
+        return isInjected() || sequenceNum == SYNTHESIZED_EVENT_SEQUENCE_NUM;
+    }
+
     void release();
 
     virtual void appendDescription(std::string& msg) const = 0;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index e161e8c..aa51e23 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -50,6 +50,7 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <limits.h>
+#include <statslog.h>
 #include <stddef.h>
 #include <time.h>
 #include <unistd.h>
@@ -2276,6 +2277,7 @@
                                                      motionEntry->downTime, motionEntry->eventTime,
                                                      motionEntry->pointerCount,
                                                      motionEntry->pointerProperties, usingCoords);
+                reportTouchEventForStatistics(*motionEntry);
                 break;
             }
 
@@ -4481,6 +4483,34 @@
     // TODO Write some statistics about how long we spend waiting.
 }
 
+/**
+ * Report the touch event latency to the statsd server.
+ * Input events are reported for statistics if:
+ * - This is a touchscreen event
+ * - InputFilter is not enabled
+ * - Event is not injected or synthesized
+ *
+ * Statistics should be reported before calling addValue, to prevent a fresh new sample
+ * from getting aggregated with the "old" data.
+ */
+void InputDispatcher::reportTouchEventForStatistics(const MotionEntry& motionEntry)
+        REQUIRES(mLock) {
+    const bool reportForStatistics = (motionEntry.source == AINPUT_SOURCE_TOUCHSCREEN) &&
+            !(motionEntry.isSynthesized()) && !mInputFilterEnabled;
+    if (!reportForStatistics) {
+        return;
+    }
+
+    if (mTouchStatistics.shouldReport()) {
+        android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(),
+                                   mTouchStatistics.getMax(), mTouchStatistics.getMean(),
+                                   mTouchStatistics.getStDev(), mTouchStatistics.getCount());
+        mTouchStatistics.reset();
+    }
+    const float latencyMicros = nanoseconds_to_microseconds(now() - motionEntry.eventTime);
+    mTouchStatistics.addValue(latencyMicros);
+}
+
 void InputDispatcher::traceInboundQueueLengthLocked() {
     if (ATRACE_ENABLED()) {
         ATRACE_INT("iq", mInboundQueue.size());
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index f2c0402..0d9d6b0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -33,6 +33,7 @@
 #include <input/InputApplication.h>
 #include <input/InputTransport.h>
 #include <input/InputWindow.h>
+#include <input/LatencyStatistics.h>
 #include <limits.h>
 #include <stddef.h>
 #include <ui/Region.h>
@@ -455,6 +456,10 @@
     void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock);
 
     // Statistics gathering.
+    static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min;
+    LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD};
+
+    void reportTouchEventForStatistics(const MotionEntry& entry);
     void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry,
                                   int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
     void traceInboundQueueLengthLocked() REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
index bccef0f..47e9b36 100644
--- a/services/inputflinger/dispatcher/InputState.h
+++ b/services/inputflinger/dispatcher/InputState.h
@@ -24,9 +24,6 @@
 
 namespace android::inputdispatcher {
 
-// Sequence number for synthesized or injected events.
-constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
-
 /* Tracks dispatched key and motion event state so that cancellation events can be
  * synthesized when events are dropped. */
 class InputState {
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index fcb94fd..1407ef7 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -3,6 +3,7 @@
     defaults: ["surfaceflinger_defaults"],
     cflags: [
         "-DLOG_TAG=\"CompositionEngine\"",
+        "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
     ],
     shared_libs: [
         "android.frameworks.vr.composer@2.0",
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..89123df 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()),
@@ -254,13 +255,17 @@
         scissor = displayBounds;
     }
 
+    uint32_t transformOrientation;
+
     if (isPrimary()) {
         sPrimaryDisplayOrientation = displayStateOrientationToTransformOrientation(orientation);
+        transformOrientation = displayStateOrientationToTransformOrientation(
+                (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1));
+    } else {
+        transformOrientation = displayStateOrientationToTransformOrientation(orientation);
     }
 
-    getCompositionDisplay()->setProjection(globalTransform,
-                                           displayStateOrientationToTransformOrientation(
-                                                   orientation),
+    getCompositionDisplay()->setProjection(globalTransform, transformOrientation,
                                            frame, viewport, scissor, needsFiltering);
 }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 52a09b3..079bc66 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -899,6 +899,7 @@
         }
         setZOrderRelativeOf(nullptr);
     }
+    mCurrentState.isRelativeOf = false;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -942,6 +943,7 @@
     mCurrentState.sequence++;
     mCurrentState.modified = true;
     mCurrentState.z = relativeZ;
+    mCurrentState.isRelativeOf = true;
 
     auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
     if (oldZOrderRelativeOf != nullptr) {
@@ -1540,7 +1542,7 @@
 bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const {
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const State& state = useDrawing ? mDrawingState : mCurrentState;
-    return state.zOrderRelativeOf != nullptr;
+    return state.isRelativeOf;
 }
 
 __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList(
@@ -1565,8 +1567,7 @@
     }
 
     for (const sp<Layer>& child : children) {
-        const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
-        if (childState.zOrderRelativeOf != nullptr) {
+        if (child->usingRelativeZ(stateSet)) {
             continue;
         }
         traverse.add(child);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 96970ac..610df25 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -172,6 +172,7 @@
 
         // If non-null, a Surface this Surface's Z-order is interpreted relative to.
         wp<Layer> zOrderRelativeOf;
+        bool isRelativeOf{false};
 
         // A list of surfaces whose Z-order is interpreted relative to ours.
         SortedVector<wp<Layer>> zOrderRelatives;
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 8494524..8271fd9 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -64,7 +64,7 @@
         const auto& layer = (*this)[i];
         auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
                                                       : layer->getDrawingState();
-        if (state.zOrderRelativeOf != nullptr) {
+        if (state.isRelativeOf) {
             continue;
         }
         layer->traverseInZOrder(stateSet, visitor);
@@ -76,7 +76,7 @@
         const auto& layer = (*this)[i];
         auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
                                                       : layer->getDrawingState();
-        if (state.zOrderRelativeOf != nullptr) {
+        if (state.isRelativeOf) {
             continue;
         }
         layer->traverseInReverseZOrder(stateSet, visitor);