Retire goldfish_dma from the guest am: 529b6cbd8b

Original change: https://android-review.googlesource.com/c/device/generic/goldfish-opengl/+/2954473

Change-Id: I7d4d0bb1401f220741c1fc19febaa2b6e095a795
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp b/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
index 81366dd..f9a7a3f 100644
--- a/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
+++ b/system/codecs/c2/decoders/avcdec/C2GoldfishAvcDec.cpp
@@ -869,15 +869,15 @@
     if (!mOldPts2Index.empty()) {
         auto iter = mOldPts2Index.find(pts);
         if (iter != mOldPts2Index.end()) {
-            mOldPts2Index.erase(iter);
             index = iter->second;
+            mOldPts2Index.erase(iter);
             found = true;
         }
     } else {
         auto iter = mPts2Index.find(pts);
         if (iter != mPts2Index.end()) {
-            mPts2Index.erase(iter);
             index = iter->second;
+            mPts2Index.erase(iter);
             found = true;
         }
     }
diff --git a/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp b/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
index 14eed1f..173dd38 100644
--- a/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
+++ b/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
@@ -816,15 +816,15 @@
     if (!mOldPts2Index.empty()) {
         auto iter = mOldPts2Index.find(pts);
         if (iter != mOldPts2Index.end()) {
-            mOldPts2Index.erase(iter);
             index = iter->second;
+            mOldPts2Index.erase(iter);
             found = true;
         }
     } else {
         auto iter = mPts2Index.find(pts);
         if (iter != mPts2Index.end()) {
-            mPts2Index.erase(iter);
             index = iter->second;
+            mPts2Index.erase(iter);
             found = true;
         }
     }
diff --git a/system/gralloc/gralloc_old.cpp b/system/gralloc/gralloc_old.cpp
index 13228e8..0fe864e 100644
--- a/system/gralloc/gralloc_old.cpp
+++ b/system/gralloc/gralloc_old.cpp
@@ -78,7 +78,7 @@
 static const bool isHidlGralloc = false;
 #endif
 
-using android::base::guest::getCurrentThreadId;
+using gfxstream::guest::getCurrentThreadId;
 
 const uint32_t CB_HANDLE_MAGIC_OLD = CB_HANDLE_MAGIC_BASE | 0x1;
 const int kBufferFdIndex = 0;
diff --git a/system/hwc3/AlternatingImageStorage.cpp b/system/hwc3/AlternatingImageStorage.cpp
new file mode 100644
index 0000000..6ca2b0b
--- /dev/null
+++ b/system/hwc3/AlternatingImageStorage.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AlternatingImageStorage.h"
+
+namespace aidl::android::hardware::graphics::composer3::impl {
+
+uint8_t* AlternatingImageStorage::getRotatingScratchBuffer(std::size_t neededSize,
+                                                           std::uint32_t imageIndex) {
+  std::size_t totalNeededSize = neededSize * kNumScratchBufferPieces;
+  if (mScratchBuffer.size() < totalNeededSize) {
+    mScratchBuffer.resize(totalNeededSize);
+  }
+
+  std::size_t bufferIndex = imageIndex % kNumScratchBufferPieces;
+  std::size_t bufferOffset = bufferIndex * neededSize;
+  return &mScratchBuffer[bufferOffset];
+}
+
+uint8_t* AlternatingImageStorage::getSpecialScratchBuffer(size_t neededSize) {
+  if (mSpecialScratchBuffer.size() < neededSize) {
+    mSpecialScratchBuffer.resize(neededSize);
+  }
+
+  return &mSpecialScratchBuffer[0];
+}
+
+}  // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/system/hwc3/AlternatingImageStorage.h b/system/hwc3/AlternatingImageStorage.h
new file mode 100644
index 0000000..31c4467
--- /dev/null
+++ b/system/hwc3/AlternatingImageStorage.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWC_ALTERNATINGIMAGESTORAGE_H
+#define ANDROID_HWC_ALTERNATINGIMAGESTORAGE_H
+
+#include <stdint.h>
+#include <vector>
+
+#include "Common.h"
+
+namespace aidl::android::hardware::graphics::composer3::impl {
+
+// Provides storage for images when transforming images with the expectation
+// that image N will no longer be used after producing image N + 1. With this,
+// the storage just needs to be 2x the needed image size and the returned buffers
+// can alternate back and forth.
+class AlternatingImageStorage {
+ public:
+  AlternatingImageStorage() = default;
+
+  uint8_t* getRotatingScratchBuffer(std::size_t neededSize, std::uint32_t imageIndex);
+
+  uint8_t* getSpecialScratchBuffer(std::size_t neededSize);
+
+ private:
+  static constexpr const int kNumScratchBufferPieces = 2;
+
+  // The main alternating storage.
+  std::vector<uint8_t> mScratchBuffer;
+
+  // Extra additional storage for one-off operations (scaling).
+  std::vector<uint8_t> mSpecialScratchBuffer;
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3::impl
+
+#endif
diff --git a/system/hwc3/Android.bp b/system/hwc3/Android.bp
index a58e125..ccbab19 100644
--- a/system/hwc3/Android.bp
+++ b/system/hwc3/Android.bp
@@ -30,7 +30,7 @@
     shared_libs: [
         "android.hardware.graphics.composer@2.1-resources",
         "android.hardware.graphics.composer@2.2-resources",
-        "android.hardware.graphics.composer3-V2-ndk",
+        "android.hardware.graphics.composer3-V3-ndk",
         "libbase",
         "libbinder_ndk",
         "libcutils",
@@ -56,6 +56,7 @@
     ],
 
     srcs: [
+        "AlternatingImageStorage.cpp",
         "ClientFrameComposer.cpp",
         "Common.cpp",
         "Composer.cpp",
@@ -89,6 +90,7 @@
     cflags: [
         "-Wall",
         "-Werror=conversion",
+        "-Wthread-safety",
     ],
 
     vintf_fragments: ["hwc3.xml"],
diff --git a/system/hwc3/Composer.h b/system/hwc3/Composer.h
index e46e951..a628643 100644
--- a/system/hwc3/Composer.h
+++ b/system/hwc3/Composer.h
@@ -18,7 +18,7 @@
 #define ANDROID_HWC_COMPOSER_H
 
 #include <aidl/android/hardware/graphics/composer3/BnComposer.h>
-#include <utils/Mutex.h>
+#include <android-base/thread_annotations.h>
 
 #include <memory>
 
@@ -45,7 +45,7 @@
     void onClientDestroyed();
 
     std::mutex mClientMutex;
-    std::weak_ptr<ComposerClient> mClient GUARDED_BY(mClientMutex);
+    std::weak_ptr<ComposerClient> mClient;
     std::condition_variable mClientDestroyedCondition;
 };
 
diff --git a/system/hwc3/ComposerClient.cpp b/system/hwc3/ComposerClient.cpp
index a7e0247..0fdcd19 100644
--- a/system/hwc3/ComposerClient.cpp
+++ b/system/hwc3/ComposerClient.cpp
@@ -28,7 +28,7 @@
 namespace {
 
 #define GET_DISPLAY_OR_RETURN_ERROR()                                        \
-    Display* display = getDisplay(displayId);                                \
+    std::shared_ptr<Display> display = getDisplay(displayId);                \
     if (display == nullptr) {                                                \
         ALOGE("%s failed to get display:%" PRIu64, __FUNCTION__, displayId); \
         return ToBinderStatus(HWC3::Error::BadDisplay);                      \
@@ -102,7 +102,7 @@
 ComposerClient::~ComposerClient() {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
+    std::lock_guard<std::mutex> lock(mDisplaysMutex);
 
     destroyDisplaysLocked();
 
@@ -116,7 +116,7 @@
 
     HWC3::Error error = HWC3::Error::None;
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
+    std::lock_guard<std::mutex> lock(mDisplaysMutex);
 
     mResources = std::make_unique<ComposerResources>();
     if (!mResources) {
@@ -165,8 +165,6 @@
                                                int64_t* layerId) {
     DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     HWC3::Error error = display->createLayer(layerId);
@@ -196,8 +194,6 @@
 ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t displayId, int64_t layerId) {
     DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     HWC3::Error error = display->destroyLayer(layerId);
@@ -228,25 +224,18 @@
     std::vector<CommandResultPayload>* commandResultPayloads) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
-    mCommandResults = std::make_unique<CommandResultWriter>(commandResultPayloads);
-
+    CommandResultWriter commandResults(commandResultPayloads);
     for (const DisplayCommand& command : commands) {
-        executeDisplayCommand(command);
-        mCommandResults->nextCommand();
+        executeDisplayCommand(commandResults, command);
+        commandResults.nextCommand();
     }
 
-    mCommandResults.reset();
-
     return ToBinderStatus(HWC3::Error::None);
 }
 
 ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t displayId, int32_t* config) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getActiveConfig(config));
@@ -256,8 +245,6 @@
                                                  std::vector<ColorMode>* colorModes) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getColorModes(colorModes));
@@ -289,8 +276,6 @@
                                                        DisplayAttribute attribute, int32_t* value) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayAttribute(config, attribute, value));
@@ -300,8 +285,6 @@
                                                           std::vector<DisplayCapability>* outCaps) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayCapabilities(outCaps));
@@ -311,8 +294,6 @@
                                                      std::vector<int32_t>* outConfigs) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayConfigs(outConfigs));
@@ -322,8 +303,6 @@
                                                             DisplayConnectionType* outType) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayConnectionType(outType));
@@ -333,8 +312,6 @@
     int64_t displayId, DisplayIdentification* outIdentification) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayIdentificationData(outIdentification));
@@ -343,8 +320,6 @@
 ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t displayId, std::string* outName) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayName(outName));
@@ -354,8 +329,6 @@
                                                          int32_t* outVsyncPeriod) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayVsyncPeriod(outVsyncPeriod));
@@ -366,8 +339,6 @@
                                                              DisplayContentSample* outSamples) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayedContentSample(maxFrames, timestamp, outSamples));
@@ -377,8 +348,6 @@
     int64_t displayId, DisplayContentSamplingAttributes* outAttributes) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayedContentSamplingAttributes(outAttributes));
@@ -388,8 +357,6 @@
     int64_t displayId, common::Transform* outOrientation) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDisplayPhysicalOrientation(outOrientation));
@@ -399,20 +366,15 @@
                                                       HdrCapabilities* outCapabilities) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getHdrCapabilities(outCapabilities));
 }
 
-ndk::ScopedAStatus ComposerClient::getOverlaySupport(OverlayProperties* properties) {
+ndk::ScopedAStatus ComposerClient::getOverlaySupport(OverlayProperties* /*properties*/) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    // no supported combinations
-    properties->combinations.clear();
-
-    return ToBinderStatus(HWC3::Error::None);
+    return ToBinderStatus(HWC3::Error::Unsupported);
 }
 
 ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(int32_t* outCount) {
@@ -428,8 +390,6 @@
     int64_t displayId, std::vector<PerFrameMetadataKey>* outKeys) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getPerFrameMetadataKeys(outKeys));
@@ -439,8 +399,6 @@
     int64_t displayId, ReadbackBufferAttributes* outAttributes) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getReadbackBufferAttributes(outAttributes));
@@ -450,8 +408,6 @@
     int64_t displayId, ndk::ScopedFileDescriptor* outAcquireFence) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getReadbackBufferFence(outAcquireFence));
@@ -461,8 +417,6 @@
                                                     std::vector<RenderIntent>* outIntents) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getRenderIntents(mode, outIntents));
@@ -472,8 +426,6 @@
                                                             std::vector<ContentType>* outTypes) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getSupportedContentTypes(outTypes));
@@ -483,8 +435,6 @@
     int64_t displayId, std::optional<common::DisplayDecorationSupport>* outSupport) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getDecorationSupport(outSupport));
@@ -494,19 +444,29 @@
     const std::shared_ptr<IComposerCallback>& callback) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     const bool isFirstRegisterCallback = mCallbacks == nullptr;
 
     mCallbacks = callback;
 
-    for (auto& [_, display] : mDisplays) {
-        display->registerCallback(callback);
+    {
+        std::lock_guard<std::mutex> lock(mDisplaysMutex);
+        for (auto& [_, display] : mDisplays) {
+            display->registerCallback(callback);
+        }
     }
 
     if (isFirstRegisterCallback) {
-        lock.unlock();
-        for (auto& [displayId, _] : mDisplays) {
+        std::vector<int64_t> displayIds;
+        {
+            std::lock_guard<std::mutex> lock(mDisplaysMutex);
+            for (auto& [displayId, _] : mDisplays) {
+                displayIds.push_back(displayId);
+            }
+        }
+
+        for (auto displayId : displayIds) {
+            DEBUG_LOG("%s initial registration, hotplug connecting display:%" PRIu64, __FUNCTION__,
+                      displayId);
             mCallbacks->onHotplug(displayId, /*connected=*/true);
         }
     }
@@ -517,8 +477,6 @@
 ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t displayId, int32_t configId) {
     DEBUG_LOG("%s display:%" PRIu64 " config:%" PRIu32, __FUNCTION__, displayId, configId);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->setActiveConfig(configId));
@@ -529,8 +487,6 @@
     VsyncPeriodChangeTimeline* outTimeline) {
     DEBUG_LOG("%s display:%" PRIu64 " config:%" PRIu32, __FUNCTION__, displayId, configId);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(
@@ -540,8 +496,6 @@
 ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t displayId, int32_t configId) {
     DEBUG_LOG("%s display:%" PRIu64 " config:%" PRIu32, __FUNCTION__, displayId, configId);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->setBootConfig(configId));
@@ -550,8 +504,6 @@
 ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(int64_t displayId) {
     DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->clearBootConfig());
@@ -561,8 +513,6 @@
                                                                  int32_t* outConfigId) {
     DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->getPreferredBootConfig(outConfigId));
@@ -602,8 +552,6 @@
 ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t displayId, bool on) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->setAutoLowLatencyMode(on));
@@ -612,8 +560,6 @@
 ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t displayId, int32_t count) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(
@@ -624,8 +570,6 @@
                                                 RenderIntent intent) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->setColorMode(mode, intent));
@@ -634,8 +578,6 @@
 ndk::ScopedAStatus ComposerClient::setContentType(int64_t displayId, ContentType type) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->setContentType(type));
@@ -645,8 +587,6 @@
     int64_t displayId, bool enable, FormatColorComponent componentMask, int64_t maxFrames) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(
@@ -656,8 +596,6 @@
 ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t displayId, PowerMode mode) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->setPowerMode(mode));
@@ -668,8 +606,6 @@
     const ndk::ScopedFileDescriptor& releaseFence) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     // Owned by mResources.
@@ -695,8 +631,6 @@
 ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t displayId, bool enabled) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->setVsyncEnabled(enabled));
@@ -705,8 +639,6 @@
 ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t displayId, int32_t timeoutMs) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    std::unique_lock<std::mutex> lock(mStateMutex);
-
     GET_DISPLAY_OR_RETURN_ERROR();
 
     return ToBinderStatus(display->setIdleTimerEnabled(timeoutMs));
@@ -721,6 +653,26 @@
     return ToBinderStatus(HWC3::Error::Unsupported);
 }
 
+ndk::ScopedAStatus ComposerClient::getDisplayConfigurations(
+    int64_t displayId, int32_t /*maxFrameIntervalNs*/,
+    std::vector<DisplayConfiguration>* outDisplayConfig) {
+    DEBUG_LOG("%s", __FUNCTION__);
+
+    GET_DISPLAY_OR_RETURN_ERROR();
+
+    return ToBinderStatus(display->getDisplayConfigurations(outDisplayConfig));
+}
+
+ndk::ScopedAStatus ComposerClient::notifyExpectedPresent(
+    int64_t displayId, const ClockMonotonicTimestamp& /*expectedPresentTime*/,
+    int32_t /*frameIntervalNs*/) {
+    DEBUG_LOG("%s", __FUNCTION__);
+
+    GET_DISPLAY_OR_RETURN_ERROR();
+
+    return ToBinderStatus(HWC3::Error::Unsupported);
+}
+
 ndk::SpAIBinder ComposerClient::createBinder() {
     auto binder = BnComposerClient::createBinder();
     AIBinder_setInheritRt(binder.get(), true);
@@ -729,126 +681,143 @@
 
 namespace {
 
-#define DISPATCH_LAYER_COMMAND(layerCmd, display, layer, field, funcName)           \
-    do {                                                                            \
-        if (layerCmd.field) {                                                       \
-            ComposerClient::executeLayerCommandSetLayer##funcName(display, layer,   \
-                                                                  *layerCmd.field); \
-        }                                                                           \
+#define DISPATCH_LAYER_COMMAND(layerCmd, commandResults, display, layer, field, funcName)         \
+    do {                                                                                          \
+        if (layerCmd.field) {                                                                     \
+            ComposerClient::executeLayerCommandSetLayer##funcName(commandResults, display, layer, \
+                                                                  *layerCmd.field);               \
+        }                                                                                         \
     } while (0)
 
-#define DISPATCH_DISPLAY_COMMAND(displayCmd, display, field, funcName)   \
-    do {                                                                 \
-        if (displayCmd.field) {                                          \
-            executeDisplayCommand##funcName(display, *displayCmd.field); \
-        }                                                                \
+#define DISPATCH_DISPLAY_COMMAND(displayCmd, commandResults, display, field, funcName)   \
+    do {                                                                                 \
+        if (displayCmd.field) {                                                          \
+            executeDisplayCommand##funcName(commandResults, display, *displayCmd.field); \
+        }                                                                                \
     } while (0)
 
-#define DISPATCH_DISPLAY_BOOL_COMMAND(displayCmd, display, field, funcName) \
-    do {                                                                    \
-        if (displayCmd.field) {                                             \
-            executeDisplayCommand##funcName(display);                       \
-        }                                                                   \
+#define DISPATCH_DISPLAY_BOOL_COMMAND(displayCmd, commandResults, display, field, funcName) \
+    do {                                                                                    \
+        if (displayCmd.field) {                                                             \
+            executeDisplayCommand##funcName(commandResults, display);                       \
+        }                                                                                   \
     } while (0)
 
-#define DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCmd, display, field, data, funcName) \
-    do {                                                                                   \
-        if (displayCmd.field) {                                                            \
-            executeDisplayCommand##funcName(display, displayCmd.data);                     \
-        }                                                                                  \
+#define DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCmd, commandResults, display, field, data, \
+                                               funcName)                                         \
+    do {                                                                                         \
+        if (displayCmd.field) {                                                                  \
+            executeDisplayCommand##funcName(commandResults, display, displayCmd.data);           \
+        }                                                                                        \
     } while (0)
 
-#define LOG_DISPLAY_COMMAND_ERROR(display, error)                                       \
-    do {                                                                                \
-        const std::string errorString = toString(error);                                \
-        ALOGE("%s: display:%" PRId64 " failed with:%s", __FUNCTION__, display->getId(), \
-              errorString.c_str());                                                     \
+#define LOG_DISPLAY_COMMAND_ERROR(display, error)                                      \
+    do {                                                                               \
+        const std::string errorString = toString(error);                               \
+        ALOGE("%s: display:%" PRId64 " failed with:%s", __FUNCTION__, display.getId(), \
+              errorString.c_str());                                                    \
     } while (0)
 
 #define LOG_LAYER_COMMAND_ERROR(display, layer, error)                                  \
     do {                                                                                \
         const std::string errorString = toString(error);                                \
         ALOGE("%s: display:%" PRId64 " layer:%" PRId64 " failed with:%s", __FUNCTION__, \
-              display->getId(), layer->getId(), errorString.c_str());                   \
+              display.getId(), layer->getId(), errorString.c_str());                    \
     } while (0)
 
 }  // namespace
 
-void ComposerClient::executeDisplayCommand(const DisplayCommand& displayCommand) {
-    Display* display = getDisplay(displayCommand.display);
+void ComposerClient::executeDisplayCommand(CommandResultWriter& commandResults,
+                                           const DisplayCommand& displayCommand) {
+    std::shared_ptr<Display> display = getDisplay(displayCommand.display);
     if (display == nullptr) {
-        mCommandResults->addError(HWC3::Error::BadDisplay);
+        commandResults.addError(HWC3::Error::BadDisplay);
         return;
     }
 
     for (const LayerCommand& layerCmd : displayCommand.layers) {
-        executeLayerCommand(display, layerCmd);
+        executeLayerCommand(commandResults, *display, layerCmd);
     }
 
-    DISPATCH_DISPLAY_COMMAND(displayCommand, display, colorTransformMatrix, SetColorTransform);
-    DISPATCH_DISPLAY_COMMAND(displayCommand, display, brightness, SetBrightness);
-    DISPATCH_DISPLAY_COMMAND(displayCommand, display, clientTarget, SetClientTarget);
-    DISPATCH_DISPLAY_COMMAND(displayCommand, display, virtualDisplayOutputBuffer, SetOutputBuffer);
-    DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCommand, display, validateDisplay,
-                                           expectedPresentTime, ValidateDisplay);
-    DISPATCH_DISPLAY_BOOL_COMMAND(displayCommand, display, acceptDisplayChanges,
+    DISPATCH_DISPLAY_COMMAND(displayCommand, commandResults, *display, colorTransformMatrix,
+                             SetColorTransform);
+    DISPATCH_DISPLAY_COMMAND(displayCommand, commandResults, *display, brightness, SetBrightness);
+    DISPATCH_DISPLAY_COMMAND(displayCommand, commandResults, *display, clientTarget,
+                             SetClientTarget);
+    DISPATCH_DISPLAY_COMMAND(displayCommand, commandResults, *display, virtualDisplayOutputBuffer,
+                             SetOutputBuffer);
+    DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCommand, commandResults, *display,
+                                           validateDisplay, expectedPresentTime, ValidateDisplay);
+    DISPATCH_DISPLAY_BOOL_COMMAND(displayCommand, commandResults, *display, acceptDisplayChanges,
                                   AcceptDisplayChanges);
-    DISPATCH_DISPLAY_BOOL_COMMAND(displayCommand, display, presentDisplay, PresentDisplay);
-    DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCommand, display, presentOrValidateDisplay,
-                                           expectedPresentTime, PresentOrValidateDisplay);
+    DISPATCH_DISPLAY_BOOL_COMMAND(displayCommand, commandResults, *display, presentDisplay,
+                                  PresentDisplay);
+    DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCommand, commandResults, *display,
+                                           presentOrValidateDisplay, expectedPresentTime,
+                                           PresentOrValidateDisplay);
 }
 
-void ComposerClient::executeLayerCommand(Display* display, const LayerCommand& layerCommand) {
-    Layer* layer = display->getLayer(layerCommand.layer);
+void ComposerClient::executeLayerCommand(CommandResultWriter& commandResults, Display& display,
+                                         const LayerCommand& layerCommand) {
+    Layer* layer = display.getLayer(layerCommand.layer);
     if (layer == nullptr) {
-        mCommandResults->addError(HWC3::Error::BadLayer);
+        commandResults.addError(HWC3::Error::BadLayer);
         return;
     }
 
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, cursorPosition, CursorPosition);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, buffer, Buffer);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, damage, SurfaceDamage);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, blendMode, BlendMode);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, color, Color);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, composition, Composition);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, dataspace, Dataspace);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, displayFrame, DisplayFrame);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, planeAlpha, PlaneAlpha);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, sidebandStream, SidebandStream);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, sourceCrop, SourceCrop);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, transform, Transform);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, visibleRegion, VisibleRegion);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, z, ZOrder);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, colorTransform, ColorTransform);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, brightness, Brightness);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, perFrameMetadata, PerFrameMetadata);
-    DISPATCH_LAYER_COMMAND(layerCommand, display, layer, perFrameMetadataBlob,
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, cursorPosition,
+                           CursorPosition);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, buffer, Buffer);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, damage, SurfaceDamage);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, blendMode, BlendMode);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, color, Color);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, composition, Composition);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, dataspace, Dataspace);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, displayFrame,
+                           DisplayFrame);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, planeAlpha, PlaneAlpha);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, sidebandStream,
+                           SidebandStream);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, sourceCrop, SourceCrop);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, transform, Transform);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, visibleRegion,
+                           VisibleRegion);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, z, ZOrder);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, colorTransform,
+                           ColorTransform);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, brightness, Brightness);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, perFrameMetadata,
+                           PerFrameMetadata);
+    DISPATCH_LAYER_COMMAND(layerCommand, commandResults, display, layer, perFrameMetadataBlob,
                            PerFrameMetadataBlobs);
 }
 
-void ComposerClient::executeDisplayCommandSetColorTransform(Display* display,
+void ComposerClient::executeDisplayCommandSetColorTransform(CommandResultWriter& commandResults,
+                                                            Display& display,
                                                             const std::vector<float>& matrix) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    auto error = display->setColorTransform(matrix);
+    auto error = display.setColorTransform(matrix);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeDisplayCommandSetBrightness(Display* display,
+void ComposerClient::executeDisplayCommandSetBrightness(CommandResultWriter& commandResults,
+                                                        Display& display,
                                                         const DisplayBrightness& brightness) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    auto error = display->setBrightness(brightness.brightness);
+    auto error = display.setBrightness(brightness.brightness);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeDisplayCommandSetClientTarget(Display* display,
+void ComposerClient::executeDisplayCommandSetClientTarget(CommandResultWriter& commandResults,
+                                                          Display& display,
                                                           const ClientTarget& clientTarget) {
     DEBUG_LOG("%s", __FUNCTION__);
 
@@ -856,142 +825,148 @@
     buffer_handle_t importedBuffer = nullptr;
 
     auto releaser = mResources->createReleaser(/*isBuffer=*/true);
-    auto error = mResources->getDisplayClientTarget(display->getId(), clientTarget.buffer,
+    auto error = mResources->getDisplayClientTarget(display.getId(), clientTarget.buffer,
                                                     &importedBuffer, releaser.get());
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
         return;
     }
 
-    error = display->setClientTarget(importedBuffer, clientTarget.buffer.fence,
-                                     clientTarget.dataspace, clientTarget.damage);
+    error = display.setClientTarget(importedBuffer, clientTarget.buffer.fence,
+                                    clientTarget.dataspace, clientTarget.damage);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
         return;
     }
 }
 
-void ComposerClient::executeDisplayCommandSetOutputBuffer(Display* display, const Buffer& buffer) {
+void ComposerClient::executeDisplayCommandSetOutputBuffer(CommandResultWriter& commandResults,
+                                                          Display& display, const Buffer& buffer) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     // Owned by mResources.
     buffer_handle_t importedBuffer = nullptr;
 
     auto releaser = mResources->createReleaser(/*isBuffer=*/true);
-    auto error = mResources->getDisplayOutputBuffer(display->getId(), buffer, &importedBuffer,
+    auto error = mResources->getDisplayOutputBuffer(display.getId(), buffer, &importedBuffer,
                                                     releaser.get());
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
         return;
     }
 
-    error = display->setOutputBuffer(importedBuffer, buffer.fence);
+    error = display.setOutputBuffer(importedBuffer, buffer.fence);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
         return;
     }
 }
 
 void ComposerClient::executeDisplayCommandValidateDisplay(
-    Display* display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
+    CommandResultWriter& commandResults, Display& display,
+    const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    auto error = display->setExpectedPresentTime(expectedPresentTime);
+    auto error = display.setExpectedPresentTime(expectedPresentTime);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 
     DisplayChanges changes;
 
-    error = display->validate(&changes);
+    error = display.validate(&changes);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     } else {
-        mCommandResults->addChanges(changes);
+        commandResults.addChanges(changes);
     }
 
-    mResources->setDisplayMustValidateState(display->getId(), false);
+    mResources->setDisplayMustValidateState(display.getId(), false);
 }
 
-void ComposerClient::executeDisplayCommandAcceptDisplayChanges(Display* display) {
+void ComposerClient::executeDisplayCommandAcceptDisplayChanges(CommandResultWriter& commandResults,
+                                                               Display& display) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    auto error = display->acceptChanges();
+    auto error = display.acceptChanges();
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
 void ComposerClient::executeDisplayCommandPresentOrValidateDisplay(
-    Display* display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
+    CommandResultWriter& commandResults, Display& display,
+    const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     // TODO: Support SKIP_VALIDATE.
 
-    auto error = display->setExpectedPresentTime(expectedPresentTime);
+    auto error = display.setExpectedPresentTime(expectedPresentTime);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 
     DisplayChanges changes;
 
-    error = display->validate(&changes);
+    error = display.validate(&changes);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     } else {
-        const int64_t displayId = display->getId();
-        mCommandResults->addChanges(changes);
-        mCommandResults->addPresentOrValidateResult(displayId,
-                                                    PresentOrValidate::Result::Validated);
+        const int64_t displayId = display.getId();
+        commandResults.addChanges(changes);
+        commandResults.addPresentOrValidateResult(displayId, PresentOrValidate::Result::Validated);
     }
 
-    mResources->setDisplayMustValidateState(display->getId(), false);
+    mResources->setDisplayMustValidateState(display.getId(), false);
 }
 
-void ComposerClient::executeDisplayCommandPresentDisplay(Display* display) {
+void ComposerClient::executeDisplayCommandPresentDisplay(CommandResultWriter& commandResults,
+                                                         Display& display) {
     DEBUG_LOG("%s", __FUNCTION__);
 
-    if (mResources->mustValidateDisplay(display->getId())) {
-        ALOGE("%s: display:%" PRIu64 " not validated", __FUNCTION__, display->getId());
-        mCommandResults->addError(HWC3::Error::NotValidated);
+    if (mResources->mustValidateDisplay(display.getId())) {
+        ALOGE("%s: display:%" PRIu64 " not validated", __FUNCTION__, display.getId());
+        commandResults.addError(HWC3::Error::NotValidated);
         return;
     }
 
     ::android::base::unique_fd displayFence;
     std::unordered_map<int64_t, ::android::base::unique_fd> layerFences;
 
-    auto error = display->present(&displayFence, &layerFences);
+    auto error = display.present(&displayFence, &layerFences);
     if (error != HWC3::Error::None) {
         LOG_DISPLAY_COMMAND_ERROR(display, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     } else {
-        const int64_t displayId = display->getId();
-        mCommandResults->addPresentFence(displayId, std::move(displayFence));
-        mCommandResults->addReleaseFences(displayId, std::move(layerFences));
+        const int64_t displayId = display.getId();
+        commandResults.addPresentFence(displayId, std::move(displayFence));
+        commandResults.addReleaseFences(displayId, std::move(layerFences));
     }
 }
 
 void ComposerClient::executeLayerCommandSetLayerCursorPosition(
-    Display* display, Layer* layer, const common::Point& cursorPosition) {
+    CommandResultWriter& commandResults, Display& display, Layer* layer,
+    const common::Point& cursorPosition) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setCursorPosition(cursorPosition);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerBuffer(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerBuffer(CommandResultWriter& commandResults,
+                                                       Display& display, Layer* layer,
                                                        const Buffer& buffer) {
     DEBUG_LOG("%s", __FUNCTION__);
 
@@ -999,218 +974,234 @@
     buffer_handle_t importedBuffer = nullptr;
 
     auto releaser = mResources->createReleaser(/*isBuffer=*/true);
-    auto error = mResources->getLayerBuffer(display->getId(), layer->getId(), buffer,
+    auto error = mResources->getLayerBuffer(display.getId(), layer->getId(), buffer,
                                             &importedBuffer, releaser.get());
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
         return;
     }
 
     error = layer->setBuffer(importedBuffer, buffer.fence);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
 void ComposerClient::executeLayerCommandSetLayerSurfaceDamage(
-    Display* display, Layer* layer, const std::vector<std::optional<common::Rect>>& damage) {
+    CommandResultWriter& commandResults, Display& display, Layer* layer,
+    const std::vector<std::optional<common::Rect>>& damage) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setSurfaceDamage(damage);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerBlendMode(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerBlendMode(CommandResultWriter& commandResults,
+                                                          Display& display, Layer* layer,
                                                           const ParcelableBlendMode& blendMode) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setBlendMode(blendMode.blendMode);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerColor(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerColor(CommandResultWriter& commandResults,
+                                                      Display& display, Layer* layer,
                                                       const Color& color) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setColor(color);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
 void ComposerClient::executeLayerCommandSetLayerComposition(
-    Display* display, Layer* layer, const ParcelableComposition& composition) {
+    CommandResultWriter& commandResults, Display& display, Layer* layer,
+    const ParcelableComposition& composition) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setCompositionType(composition.composition);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerDataspace(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerDataspace(CommandResultWriter& commandResults,
+                                                          Display& display, Layer* layer,
                                                           const ParcelableDataspace& dataspace) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setDataspace(dataspace.dataspace);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerDisplayFrame(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerDisplayFrame(CommandResultWriter& commandResults,
+                                                             Display& display, Layer* layer,
                                                              const common::Rect& rect) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setDisplayFrame(rect);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerPlaneAlpha(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerPlaneAlpha(CommandResultWriter& commandResults,
+                                                           Display& display, Layer* layer,
                                                            const PlaneAlpha& planeAlpha) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setPlaneAlpha(planeAlpha.alpha);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
 void ComposerClient::executeLayerCommandSetLayerSidebandStream(
-    Display* display, Layer* layer, const aidl::android::hardware::common::NativeHandle& handle) {
+    CommandResultWriter& commandResults, Display& display, Layer* layer,
+    const aidl::android::hardware::common::NativeHandle& handle) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     // Owned by mResources.
     buffer_handle_t importedStream = nullptr;
 
     auto releaser = mResources->createReleaser(/*isBuffer=*/false);
-    auto error = mResources->getLayerSidebandStream(display->getId(), layer->getId(), handle,
+    auto error = mResources->getLayerSidebandStream(display.getId(), layer->getId(), handle,
                                                     &importedStream, releaser.get());
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
         return;
     }
 
     error = layer->setSidebandStream(importedStream);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerSourceCrop(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerSourceCrop(CommandResultWriter& commandResults,
+                                                           Display& display, Layer* layer,
                                                            const common::FRect& sourceCrop) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setSourceCrop(sourceCrop);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerTransform(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerTransform(CommandResultWriter& commandResults,
+                                                          Display& display, Layer* layer,
                                                           const ParcelableTransform& transform) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setTransform(transform.transform);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
 void ComposerClient::executeLayerCommandSetLayerVisibleRegion(
-    Display* display, Layer* layer, const std::vector<std::optional<common::Rect>>& visibleRegion) {
+    CommandResultWriter& commandResults, Display& display, Layer* layer,
+    const std::vector<std::optional<common::Rect>>& visibleRegion) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setVisibleRegion(visibleRegion);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerZOrder(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerZOrder(CommandResultWriter& commandResults,
+                                                       Display& display, Layer* layer,
                                                        const ZOrder& zOrder) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setZOrder(zOrder.z);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
 void ComposerClient::executeLayerCommandSetLayerPerFrameMetadata(
-    Display* display, Layer* layer,
+    CommandResultWriter& commandResults, Display& display, Layer* layer,
     const std::vector<std::optional<PerFrameMetadata>>& perFrameMetadata) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setPerFrameMetadata(perFrameMetadata);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
 void ComposerClient::executeLayerCommandSetLayerColorTransform(
-    Display* display, Layer* layer, const std::vector<float>& colorTransform) {
+    CommandResultWriter& commandResults, Display& display, Layer* layer,
+    const std::vector<float>& colorTransform) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setColorTransform(colorTransform);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-void ComposerClient::executeLayerCommandSetLayerBrightness(Display* display, Layer* layer,
+void ComposerClient::executeLayerCommandSetLayerBrightness(CommandResultWriter& commandResults,
+                                                           Display& display, Layer* layer,
                                                            const LayerBrightness& brightness) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setBrightness(brightness.brightness);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
 void ComposerClient::executeLayerCommandSetLayerPerFrameMetadataBlobs(
-    Display* display, Layer* layer,
+    CommandResultWriter& commandResults, Display& display, Layer* layer,
     const std::vector<std::optional<PerFrameMetadataBlob>>& perFrameMetadataBlob) {
     DEBUG_LOG("%s", __FUNCTION__);
 
     auto error = layer->setPerFrameMetadataBlobs(perFrameMetadataBlob);
     if (error != HWC3::Error::None) {
         LOG_LAYER_COMMAND_ERROR(display, layer, error);
-        mCommandResults->addError(error);
+        commandResults.addError(error);
     }
 }
 
-Display* ComposerClient::getDisplay(int64_t displayId) {
+std::shared_ptr<Display> ComposerClient::getDisplay(int64_t displayId) {
+    std::lock_guard<std::mutex> lock(mDisplaysMutex);
+
     auto it = mDisplays.find(displayId);
     if (it == mDisplays.end()) {
         ALOGE("%s: no display:%" PRIu64, __FUNCTION__, displayId);
         return nullptr;
     }
-    return it->second.get();
+    return it->second;
 }
 
 HWC3::Error ComposerClient::createDisplaysLocked() {
@@ -1249,7 +1240,7 @@
         return HWC3::Error::NoResources;
     }
 
-    auto display = std::make_unique<Display>(mComposer, displayId);
+    auto display = std::make_shared<Display>(mComposer, displayId);
     if (display == nullptr) {
         ALOGE("%s failed to allocate display", __FUNCTION__);
         return HWC3::Error::NoResources;
@@ -1339,21 +1330,20 @@
             configId, static_cast<int>(width), static_cast<int>(height), static_cast<int>(dpiX),
             static_cast<int>(dpiY), static_cast<int>(refreshRate))};
         {
-            std::unique_lock<std::mutex> lock(mStateMutex);
+            std::lock_guard<std::mutex> lock(mDisplaysMutex);
             createDisplayLocked(displayId, configId, configs);
         }
 
-        ALOGI("Connecting display:%" PRIu32 " w:%" PRIu32 " h:%" PRIu32 " dpiX:%" PRIu32
+        ALOGI("Hotplug connecting display:%" PRIu32 " w:%" PRIu32 " h:%" PRIu32 " dpiX:%" PRIu32
               " dpiY %" PRIu32 "fps %" PRIu32,
               id, width, height, dpiX, dpiY, refreshRate);
         mCallbacks->onHotplug(displayId, /*connected=*/true);
     } else {
-        ALOGI("Disconnecting display:%" PRIu64, displayId);
+        ALOGI("Hotplug disconnecting display:%" PRIu64, displayId);
         mCallbacks->onHotplug(displayId, /*connected=*/false);
 
-        Display* display = getDisplay(displayId);
-        if (display != nullptr) {
-            std::unique_lock<std::mutex> lock(mStateMutex);
+        {
+            std::lock_guard<std::mutex> lock(mDisplaysMutex);
             destroyDisplayLocked(displayId);
         }
     }
@@ -1361,4 +1351,4 @@
     return HWC3::Error::None;
 }
 
-}  // namespace aidl::android::hardware::graphics::composer3::impl
\ No newline at end of file
+}  // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/system/hwc3/ComposerClient.h b/system/hwc3/ComposerClient.h
index 9b76d41..2cf198f 100644
--- a/system/hwc3/ComposerClient.h
+++ b/system/hwc3/ComposerClient.h
@@ -18,7 +18,7 @@
 #define ANDROID_HWC_COMPOSERCLIENT_H
 
 #include <aidl/android/hardware/graphics/composer3/BnComposerClient.h>
-#include <utils/Mutex.h>
+#include <android-base/thread_annotations.h>
 
 #include <memory>
 
@@ -118,6 +118,11 @@
     ndk::ScopedAStatus setIdleTimerEnabled(int64_t displayId, int32_t timeoutMs) override;
     ndk::ScopedAStatus setRefreshRateChangedCallbackDebugEnabled(int64_t displayId,
                                                                  bool enabled) override;
+    ndk::ScopedAStatus getDisplayConfigurations(int64_t displayId, int32_t maxFrameIntervalNs,
+                                                std::vector<DisplayConfiguration>*) override;
+    ndk::ScopedAStatus notifyExpectedPresent(int64_t displayId,
+                                             const ClockMonotonicTimestamp& expectedPresentTime,
+                                             int32_t maxFrameIntervalNs) override;
 
    protected:
     ndk::SpAIBinder createBinder() override;
@@ -125,72 +130,94 @@
    private:
     class CommandResultWriter;
 
-    void executeDisplayCommand(const DisplayCommand& displayCommand);
-    void executeLayerCommand(Display* display, const LayerCommand& layerCommand);
+    void executeDisplayCommand(CommandResultWriter& commandResults,
+                               const DisplayCommand& displayCommand);
 
-    void executeDisplayCommandSetColorTransform(Display* display, const std::vector<float>& matrix);
-    void executeDisplayCommandSetBrightness(Display* display, const DisplayBrightness& brightness);
-    void executeDisplayCommandSetClientTarget(Display* display, const ClientTarget& command);
-    void executeDisplayCommandSetOutputBuffer(Display* display, const Buffer& buffer);
+    void executeLayerCommand(CommandResultWriter& commandResults, Display& display,
+                             const LayerCommand& layerCommand);
+
+    void executeDisplayCommandSetColorTransform(CommandResultWriter& commandResults,
+                                                Display& display, const std::vector<float>& matrix);
+    void executeDisplayCommandSetBrightness(CommandResultWriter& commandResults, Display& display,
+                                            const DisplayBrightness& brightness);
+    void executeDisplayCommandSetClientTarget(CommandResultWriter& commandResults, Display& display,
+                                              const ClientTarget& command);
+    void executeDisplayCommandSetOutputBuffer(CommandResultWriter& commandResults, Display& display,
+                                              const Buffer& buffer);
     void executeDisplayCommandValidateDisplay(
-        Display* display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime);
-    void executeDisplayCommandAcceptDisplayChanges(Display* display);
+        CommandResultWriter& commandResults, Display& display,
+        const std::optional<ClockMonotonicTimestamp> expectedPresentTime);
+    void executeDisplayCommandAcceptDisplayChanges(CommandResultWriter& commandResults,
+                                                   Display& display);
     void executeDisplayCommandPresentOrValidateDisplay(
-        Display* display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime);
-    void executeDisplayCommandPresentDisplay(Display* display);
+        CommandResultWriter& commandResults, Display& display,
+        const std::optional<ClockMonotonicTimestamp> expectedPresentTime);
+    void executeDisplayCommandPresentDisplay(CommandResultWriter& commandResults, Display& display);
 
-    void executeLayerCommandSetLayerCursorPosition(Display* display, Layer* layer,
+    void executeLayerCommandSetLayerCursorPosition(CommandResultWriter& commandResults,
+                                                   Display& display, Layer* layer,
                                                    const common::Point& cursorPosition);
-    void executeLayerCommandSetLayerBuffer(Display* display, Layer* layer, const Buffer& buffer);
+    void executeLayerCommandSetLayerBuffer(CommandResultWriter& commandResults, Display& display,
+                                           Layer* layer, const Buffer& buffer);
     void executeLayerCommandSetLayerSurfaceDamage(
-        Display* display, Layer* layer, const std::vector<std::optional<common::Rect>>& damage);
-    void executeLayerCommandSetLayerBlendMode(Display* display, Layer* layer,
-                                              const ParcelableBlendMode& blendMode);
-    void executeLayerCommandSetLayerColor(Display* display, Layer* layer, const Color& color);
-    void executeLayerCommandSetLayerComposition(Display* display, Layer* layer,
+        CommandResultWriter& commandResults, Display& display, Layer* layer,
+        const std::vector<std::optional<common::Rect>>& damage);
+    void executeLayerCommandSetLayerBlendMode(CommandResultWriter& commandResults, Display& display,
+                                              Layer* layer, const ParcelableBlendMode& blendMode);
+    void executeLayerCommandSetLayerColor(CommandResultWriter& commandResults, Display& display,
+                                          Layer* layer, const Color& color);
+    void executeLayerCommandSetLayerComposition(CommandResultWriter& commandResults,
+                                                Display& display, Layer* layer,
                                                 const ParcelableComposition& composition);
-    void executeLayerCommandSetLayerDataspace(Display* display, Layer* layer,
-                                              const ParcelableDataspace& dataspace);
-    void executeLayerCommandSetLayerDisplayFrame(Display* display, Layer* layer,
+    void executeLayerCommandSetLayerDataspace(CommandResultWriter& commandResults, Display& display,
+                                              Layer* layer, const ParcelableDataspace& dataspace);
+    void executeLayerCommandSetLayerDisplayFrame(CommandResultWriter& commandResults,
+                                                 Display& display, Layer* layer,
                                                  const common::Rect& rect);
-    void executeLayerCommandSetLayerPlaneAlpha(Display* display, Layer* layer,
+    void executeLayerCommandSetLayerPlaneAlpha(CommandResultWriter& commandResults,
+                                               Display& display, Layer* layer,
                                                const PlaneAlpha& planeAlpha);
     void executeLayerCommandSetLayerSidebandStream(
-        Display* display, Layer* layer,
+        CommandResultWriter& commandResults, Display& display, Layer* layer,
         const aidl::android::hardware::common::NativeHandle& sidebandStream);
-    void executeLayerCommandSetLayerSourceCrop(Display* display, Layer* layer,
+    void executeLayerCommandSetLayerSourceCrop(CommandResultWriter& commandResults,
+                                               Display& display, Layer* layer,
                                                const common::FRect& sourceCrop);
-    void executeLayerCommandSetLayerTransform(Display* display, Layer* layer,
-                                              const ParcelableTransform& transform);
+    void executeLayerCommandSetLayerTransform(CommandResultWriter& commandResults, Display& display,
+                                              Layer* layer, const ParcelableTransform& transform);
     void executeLayerCommandSetLayerVisibleRegion(
-        Display* display, Layer* layer,
+        CommandResultWriter& commandResults, Display& display, Layer* layer,
         const std::vector<std::optional<common::Rect>>& visibleRegion);
-    void executeLayerCommandSetLayerZOrder(Display* display, Layer* layer, const ZOrder& zOrder);
+    void executeLayerCommandSetLayerZOrder(CommandResultWriter& commandResults, Display& display,
+                                           Layer* layer, const ZOrder& zOrder);
     void executeLayerCommandSetLayerPerFrameMetadata(
-        Display* display, Layer* layer,
+        CommandResultWriter& commandResults, Display& display, Layer* layer,
         const std::vector<std::optional<PerFrameMetadata>>& perFrameMetadata);
-    void executeLayerCommandSetLayerColorTransform(Display* display, Layer* layer,
+    void executeLayerCommandSetLayerColorTransform(CommandResultWriter& commandResults,
+                                                   Display& display, Layer* layer,
                                                    const std::vector<float>& colorTransform);
-    void executeLayerCommandSetLayerBrightness(Display* display, Layer* layer,
+    void executeLayerCommandSetLayerBrightness(CommandResultWriter& commandResults,
+                                               Display& display, Layer* layer,
                                                const LayerBrightness& brightness);
     void executeLayerCommandSetLayerPerFrameMetadataBlobs(
-        Display* display, Layer* layer,
+        CommandResultWriter& commandResults, Display& display, Layer* layer,
         const std::vector<std::optional<PerFrameMetadataBlob>>& perFrameMetadataBlob);
 
     // Returns the display with the given id or nullptr if not found.
-    Display* getDisplay(int64_t displayId);
+    std::shared_ptr<Display> getDisplay(int64_t displayId);
 
     // Finds the Cuttlefish/Goldfish specific configuration and initializes the
     // displays.
-    HWC3::Error createDisplaysLocked();
+    HWC3::Error createDisplaysLocked() EXCLUSIVE_LOCKS_REQUIRED(mDisplaysMutex);
 
     // Creates a display with the given properties.
     HWC3::Error createDisplayLocked(int64_t displayId, int32_t activeConfigId,
-                                    const std::vector<DisplayConfig>& configs);
+                                    const std::vector<DisplayConfig>& configs)
+        EXCLUSIVE_LOCKS_REQUIRED(mDisplaysMutex);
 
-    HWC3::Error destroyDisplaysLocked();
+    HWC3::Error destroyDisplaysLocked() EXCLUSIVE_LOCKS_REQUIRED(mDisplaysMutex);
 
-    HWC3::Error destroyDisplayLocked(int64_t displayId);
+    HWC3::Error destroyDisplayLocked(int64_t displayId) EXCLUSIVE_LOCKS_REQUIRED(mDisplaysMutex);
 
     HWC3::Error handleHotplug(bool connected,   //
                               uint32_t id,      //
@@ -200,9 +227,8 @@
                               uint32_t dpiY,    //
                               uint32_t refreshRate);
 
-    std::mutex mStateMutex;
-
-    std::map<int64_t, std::unique_ptr<Display>> mDisplays;
+    std::mutex mDisplaysMutex;
+    std::map<int64_t, std::shared_ptr<Display>> mDisplays GUARDED_BY(mDisplaysMutex);
 
     // The onHotplug(), onVsync(), etc callbacks registered by SurfaceFlinger.
     std::shared_ptr<IComposerCallback> mCallbacks;
@@ -213,10 +239,6 @@
     // the host using opengl. Owned by Device.
     FrameComposer* mComposer = nullptr;
 
-    // For the duration of a executeCommands(), the helper used to collect
-    // individual command results.
-    std::unique_ptr<CommandResultWriter> mCommandResults;
-
     // Manages importing and caching gralloc buffers for displays and layers.
     std::unique_ptr<ComposerResources> mResources;
 };
diff --git a/system/hwc3/Display.cpp b/system/hwc3/Display.cpp
index 3142e48..c221c25 100644
--- a/system/hwc3/Display.cpp
+++ b/system/hwc3/Display.cpp
@@ -262,6 +262,30 @@
     return HWC3::Error::None;
 }
 
+HWC3::Error Display::getDisplayConfigurations(std::vector<DisplayConfiguration>* outConfigs) {
+  DEBUG_LOG("%s: display:%" PRId64, __FUNCTION__, mId);
+
+  std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+  outConfigs->clear();
+  outConfigs->reserve(mConfigs.size());
+
+  for (const auto& [configId, displayConfig] : mConfigs) {
+    DisplayConfiguration displayConfiguration;
+    displayConfiguration.configId = configId;
+    displayConfiguration.width = displayConfig.getWidth();
+    displayConfiguration.height = displayConfig.getHeight();
+    displayConfiguration.dpi = { static_cast<float>(displayConfig.getDpiX()),
+                                static_cast<float>(displayConfig.getDpiY()) };
+    displayConfiguration.vsyncPeriod = displayConfig.getVsyncPeriod();
+    displayConfiguration.configGroup = displayConfig.getConfigGroup();
+
+    outConfigs->emplace_back(displayConfiguration);
+  }
+
+  return HWC3::Error::None;
+}
+
 HWC3::Error Display::getDisplayConnectionType(DisplayConnectionType* outType) {
     if (IsCuttlefishFoldable() || IsAutoDevice()) {
         // Android Auto OS needs to set all displays to INTERNAL since they're used
diff --git a/system/hwc3/Display.h b/system/hwc3/Display.h
index 8ed6f91..78cd3dc 100644
--- a/system/hwc3/Display.h
+++ b/system/hwc3/Display.h
@@ -83,6 +83,7 @@
     HWC3::Error getColorModes(std::vector<ColorMode>* outColorModes);
     HWC3::Error getDisplayCapabilities(std::vector<DisplayCapability>* caps);
     HWC3::Error getDisplayConfigs(std::vector<int32_t>* configs);
+    HWC3::Error getDisplayConfigurations(std::vector<DisplayConfiguration>* outConfigs);
     HWC3::Error getDisplayConnectionType(DisplayConnectionType* outType);
     HWC3::Error getDisplayIdentificationData(DisplayIdentification* outIdentification);
     HWC3::Error getDisplayName(std::string* outName);
diff --git a/system/hwc3/GuestFrameComposer.cpp b/system/hwc3/GuestFrameComposer.cpp
index f4333fc..f4c9267 100644
--- a/system/hwc3/GuestFrameComposer.cpp
+++ b/system/hwc3/GuestFrameComposer.cpp
@@ -802,11 +802,12 @@
                 continue;
             }
 
-            HWC3::Error error = composeLayerInto(layer,                          //
-                                                 compositionResultBufferData,    //
-                                                 compositionResultBufferWidth,   //
-                                                 compositionResultBufferHeight,  //
-                                                 compositionResultBufferStride,  //
+            HWC3::Error error = composeLayerInto(displayInfo.compositionIntermediateStorage,  //
+                                                 layer,                                       //
+                                                 compositionResultBufferData,                 //
+                                                 compositionResultBufferWidth,                //
+                                                 compositionResultBufferHeight,               //
+                                                 compositionResultBufferStride,               //
                                                  4);
             if (error != HWC3::Error::None) {
                 ALOGE("%s: display:%" PRIu32 " failed to compose layer:%" PRIu64, __FUNCTION__,
@@ -878,12 +879,14 @@
     return true;
 }
 
-HWC3::Error GuestFrameComposer::composeLayerInto(Layer* srcLayer,                     //
-                                                 std::uint8_t* dstBuffer,             //
-                                                 std::uint32_t dstBufferWidth,        //
-                                                 std::uint32_t dstBufferHeight,       //
-                                                 std::uint32_t dstBufferStrideBytes,  //
-                                                 std::uint32_t dstBufferBytesPerPixel) {
+HWC3::Error GuestFrameComposer::composeLayerInto(
+    AlternatingImageStorage& compositionIntermediateStorage,
+    Layer* srcLayer,                     //
+    std::uint8_t* dstBuffer,             //
+    std::uint32_t dstBufferWidth,        //
+    std::uint32_t dstBufferHeight,       //
+    std::uint32_t dstBufferStrideBytes,  //
+    std::uint32_t dstBufferBytesPerPixel) {
     ATRACE_CALL();
 
     libyuv::RotationMode rotation = GetRotationFromTransform(srcLayer->getTransform());
@@ -955,10 +958,10 @@
     // framebuffer) is one of them, so only N-1 temporary buffers are needed.
     // Vertical flip is not taken into account because it can be done together
     // with any other operation.
-    int neededScratchBuffers = (needsFill ? 1 : 0) + (needsConversion ? 1 : 0) +
-                               (needsScaling ? 1 : 0) + (needsRotation ? 1 : 0) +
-                               (needsAttenuation ? 1 : 0) + (needsBlending ? 1 : 0) +
-                               (needsCopy ? 1 : 0) - 1;
+    int neededIntermediateImages = (needsFill ? 1 : 0) + (needsConversion ? 1 : 0) +
+                                   (needsScaling ? 1 : 0) + (needsRotation ? 1 : 0) +
+                                   (needsAttenuation ? 1 : 0) + (needsBlending ? 1 : 0) +
+                                   (needsCopy ? 1 : 0) - 1;
 
     uint32_t mScratchBufferWidth =
         static_cast<uint32_t>(srcLayerDisplayFrame.right - srcLayerDisplayFrame.left);
@@ -968,10 +971,10 @@
         AlignToPower2(mScratchBufferWidth * dstBufferBytesPerPixel, 4);
     uint32_t mScratchBufferSizeBytes = mScratchBufferHeight * mScratchBufferStrideBytes;
 
-    for (uint32_t i = 0; i < neededScratchBuffers; i++) {
-        BufferSpec mScratchBufferspec(getRotatingScratchBuffer(mScratchBufferSizeBytes, i),
-                                      mScratchBufferWidth, mScratchBufferHeight,
-                                      mScratchBufferStrideBytes);
+    for (uint32_t i = 0; i < neededIntermediateImages; i++) {
+        BufferSpec mScratchBufferspec(
+            compositionIntermediateStorage.getRotatingScratchBuffer(mScratchBufferSizeBytes, i),
+            mScratchBufferWidth, mScratchBufferHeight, mScratchBufferStrideBytes);
         dstBufferStack.push_back(mScratchBufferspec);
     }
 
@@ -1004,7 +1007,7 @@
             uint32_t srcWidth = srcLayerSpec.cropWidth;
             uint32_t srcHeight = srcLayerSpec.cropHeight;
             uint32_t dst_stride_bytes = AlignToPower2(srcWidth * dstBufferBytesPerPixel, 4);
-            uint32_t needed_size = dst_stride_bytes * srcHeight;
+            uint32_t neededSize = dst_stride_bytes * srcHeight;
             dstBufferSpec.width = srcWidth;
             dstBufferSpec.height = srcHeight;
             // Adjust the stride accordingly
@@ -1016,7 +1019,8 @@
 
             // In case of a scale, the source frame may be bigger than the default tmp
             // buffer size
-            dstBufferSpec.buffer = getSpecialScratchBuffer(needed_size);
+            dstBufferSpec.buffer =
+                compositionIntermediateStorage.getSpecialScratchBuffer(neededSize);
         }
 
         int retval = DoConversion(srcLayerSpec, dstBufferSpec, needsVFlip);
@@ -1136,25 +1140,4 @@
     return HWC3::Error::None;
 }
 
-uint8_t* GuestFrameComposer::getRotatingScratchBuffer(std::size_t neededSize, std::uint32_t order) {
-    static constexpr const int kNumScratchBufferPieces = 2;
-
-    std::size_t totalNeededSize = neededSize * kNumScratchBufferPieces;
-    if (mScratchBuffer.size() < totalNeededSize) {
-        mScratchBuffer.resize(totalNeededSize);
-    }
-
-    std::size_t bufferIndex = order % kNumScratchBufferPieces;
-    std::size_t bufferOffset = bufferIndex * neededSize;
-    return &mScratchBuffer[bufferOffset];
-}
-
-uint8_t* GuestFrameComposer::getSpecialScratchBuffer(size_t neededSize) {
-    if (mSpecialScratchBuffer.size() < neededSize) {
-        mSpecialScratchBuffer.resize(neededSize);
-    }
-
-    return &mSpecialScratchBuffer[0];
-}
-
 }  // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/system/hwc3/GuestFrameComposer.h b/system/hwc3/GuestFrameComposer.h
index 196df3e..2d2ca20 100644
--- a/system/hwc3/GuestFrameComposer.h
+++ b/system/hwc3/GuestFrameComposer.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_HWC_GUESTFRAMECOMPOSER_H
 #define ANDROID_HWC_GUESTFRAMECOMPOSER_H
 
+#include "AlternatingImageStorage.h"
 #include "Common.h"
 #include "Display.h"
 #include "DrmClient.h"
@@ -77,9 +78,9 @@
     bool canComposeLayer(Layer* layer);
 
     // Composes the given layer into the given destination buffer.
-    HWC3::Error composeLayerInto(Layer* layer, std::uint8_t* dstBuffer,
-                                 std::uint32_t dstBufferWidth, std::uint32_t dstBufferHeight,
-                                 std::uint32_t dstBufferStrideBytes,
+    HWC3::Error composeLayerInto(AlternatingImageStorage& storage, Layer* layer,
+                                 std::uint8_t* dstBuffer, std::uint32_t dstBufferWidth,
+                                 std::uint32_t dstBufferHeight, std::uint32_t dstBufferStrideBytes,
                                  std::uint32_t dstBufferBytesPerPixel);
 
     struct DisplayInfo {
@@ -87,6 +88,9 @@
         buffer_handle_t compositionResultBuffer = nullptr;
 
         std::shared_ptr<DrmBuffer> compositionResultDrmBuffer;
+
+        // Scratch storage space for intermediate images during composition.
+        AlternatingImageStorage compositionIntermediateStorage;
     };
 
     std::unordered_map<int64_t, DisplayInfo> mDisplayInfos;
@@ -99,17 +103,11 @@
     // spamming logcat with DRM commit failures.
     bool mPresentDisabled = false;
 
-    uint8_t* getRotatingScratchBuffer(std::size_t neededSize, std::uint32_t order);
-    uint8_t* getSpecialScratchBuffer(std::size_t neededSize);
-
     HWC3::Error applyColorTransformToRGBA(const std::array<float, 16>& colorTransform,  //
                                           std::uint8_t* buffer,                         //
                                           std::uint32_t bufferWidth,                    //
                                           std::uint32_t bufferHeight,                   //
                                           std::uint32_t bufferStrideBytes);
-
-    std::vector<uint8_t> mScratchBuffer;
-    std::vector<uint8_t> mSpecialScratchBuffer;
 };
 
 }  // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/system/hwc3/hwc3.xml b/system/hwc3/hwc3.xml
index 861b4b7..7f0d8b7 100644
--- a/system/hwc3/hwc3.xml
+++ b/system/hwc3/hwc3.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.graphics.composer3</name>
-        <version>2</version>
+        <version>3</version>
         <interface>
             <name>IComposer</name>
             <instance>default</instance>