SF: Don't cache display modes in HWComposer

The display modes should be stored only in DisplayDevice.
Having the state also in HWComposer is unnesesary and hard to
keep in sync with SF, e.g. during hotplug processing of
displays which can change their supported modes.

Any HWC calls which need to validate their parameters need
to go through display device. This additinally makes the
code more undestandable.

Bug: 159590486
Test: presubmit
Change-Id: I40b03c09a5fd6092fca0682d602deb70db022fa5
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 39ae2fd..ec81ff7 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -377,7 +377,7 @@
                displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
         // The HWC doesn't support present fences, so use the refresh
         // timestamp instead.
-        const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
+        const nsecs_t actualPresentTime = display->getRefreshTimestamp();
         mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime);
         mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
                                                actualPresentTime,
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
index 6559ed8..4502eee 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <ui/Size.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/StrongPointer.h>
@@ -71,7 +72,7 @@
 
     virtual void dumpAsString(String8& result) const = 0;
 
-    virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
+    virtual void resizeBuffers(const ui::Size&) = 0;
 
     virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
index 31b5f95..168e433 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
@@ -18,6 +18,7 @@
 
 #include <compositionengine/DisplaySurface.h>
 #include <gmock/gmock.h>
+#include <ui/Size.h>
 #include <utils/String8.h>
 
 namespace android::compositionengine::mock {
@@ -32,7 +33,7 @@
     MOCK_METHOD0(advanceFrame, status_t());
     MOCK_METHOD0(onFrameCommitted, void());
     MOCK_CONST_METHOD1(dumpAsString, void(String8& result));
-    MOCK_METHOD2(resizeBuffers, void(uint32_t, uint32_t));
+    MOCK_METHOD1(resizeBuffers, void(const ui::Size&));
     MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&());
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index b47f7fd..3bef77d 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -96,8 +96,7 @@
 }
 
 void RenderSurface::setDisplaySize(const ui::Size& size) {
-    mDisplaySurface->resizeBuffers(static_cast<uint32_t>(size.width),
-                                   static_cast<uint32_t>(size.height));
+    mDisplaySurface->resizeBuffers(size);
     mSize = size;
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 3133e90..ab00385 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -85,16 +85,15 @@
     MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool());
     MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t));
     MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync));
-    MOCK_CONST_METHOD1(getRefreshTimestamp, nsecs_t(PhysicalDisplayId));
     MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId));
-    MOCK_CONST_METHOD1(getModes, DisplayModes(PhysicalDisplayId));
-    MOCK_CONST_METHOD1(getActiveMode, DisplayModePtr(PhysicalDisplayId));
+    MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId));
+    MOCK_CONST_METHOD1(getActiveMode, std::optional<hal::HWConfigId>(PhysicalDisplayId));
     MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(PhysicalDisplayId));
     MOCK_METHOD3(setActiveColorMode, status_t(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent));
     MOCK_CONST_METHOD0(isUsingVrComposer, bool());
     MOCK_CONST_METHOD1(getDisplayConnectionType, DisplayConnectionType(PhysicalDisplayId));
     MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(PhysicalDisplayId));
-    MOCK_CONST_METHOD1(getDisplayVsyncPeriod, nsecs_t(PhysicalDisplayId));
+    MOCK_CONST_METHOD2(getDisplayVsyncPeriod, status_t(PhysicalDisplayId, nsecs_t*));
     MOCK_METHOD4(setActiveModeWithConstraints,
                  status_t(PhysicalDisplayId, hal::HWConfigId,
                           const hal::VsyncPeriodChangeConstraints&,
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index cd39733..5ef5d7b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -119,9 +119,10 @@
  */
 
 TEST_F(RenderSurfaceTest, setDisplaySizeAppliesChange) {
-    EXPECT_CALL(*mDisplaySurface, resizeBuffers(640, 480)).Times(1);
+    const ui::Size size(640, 480);
+    EXPECT_CALL(*mDisplaySurface, resizeBuffers(size)).Times(1);
 
-    mSurface.setDisplaySize(ui::Size(640, 480));
+    mSurface.setDisplaySize(size);
 }
 
 /*
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b4a3ed1..a785968 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -179,6 +179,31 @@
     return nullptr;
 }
 
+nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
+    const auto physicalId = getPhysicalId();
+    if (!mHwComposer.isConnected(physicalId)) {
+        return 0;
+    }
+
+    nsecs_t vsyncPeriod;
+    const auto status = mHwComposer.getDisplayVsyncPeriod(physicalId, &vsyncPeriod);
+    if (status == NO_ERROR) {
+        return vsyncPeriod;
+    }
+
+    return getActiveMode()->getFps().getPeriodNsecs();
+}
+
+nsecs_t DisplayDevice::getRefreshTimestamp() const {
+    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    const auto vsyncPeriodNanos = getVsyncPeriodFromHWC();
+    return now - ((now - mLastHwVsync) % vsyncPeriodNanos);
+}
+
+void DisplayDevice::onVsync(nsecs_t timestamp) {
+    mLastHwVsync = timestamp;
+}
+
 ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
     return mCompositionDisplay->getState().dataspace;
 }
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 6f07964..b4db933 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -176,6 +176,10 @@
     // set-top boxes after a hotplug reconnect.
     DisplayModePtr getMode(DisplayModeId) const;
 
+    void onVsync(nsecs_t timestamp);
+    nsecs_t getVsyncPeriodFromHWC() const;
+    nsecs_t getRefreshTimestamp() const;
+
     // release HWC resources (if any) for removable displays
     void disconnect();
 
@@ -207,6 +211,8 @@
     DisplayModeId mActiveModeId;
     const DisplayModes mSupportedModes;
 
+    std::atomic<nsecs_t> mLastHwVsync = 0;
+
     // TODO(b/74619554): Remove special cases for primary display.
     const bool mIsPrimary;
 
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 61c1b61..31d1245 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -22,6 +22,7 @@
 
 #include <android-base/stringprintf.h>
 #include <android/configuration.h>
+#include <ui/Size.h>
 #include <utils/Timers.h>
 
 #include <cstddef>
@@ -113,6 +114,7 @@
 
     int32_t getWidth() const { return mWidth; }
     int32_t getHeight() const { return mHeight; }
+    ui::Size getSize() const { return {mWidth, mHeight}; }
     Fps getFps() const { return mFps; }
     nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
     float getDpiX() const { return mDpiX; }
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 3e856bb..f7fc162 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -58,11 +58,10 @@
 
 FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
                                        const sp<IGraphicBufferConsumer>& consumer,
-                                       uint32_t maxWidth, uint32_t maxHeight)
+                                       const ui::Size& size, const ui::Size& maxSize)
       : ConsumerBase(consumer),
         mDisplayId(displayId),
-        mMaxWidth(maxWidth),
-        mMaxHeight(maxHeight),
+        mMaxSize(maxSize),
         mCurrentBufferSlot(-1),
         mCurrentBuffer(),
         mCurrentFence(Fence::NO_FENCE),
@@ -77,15 +76,14 @@
     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
                                        GRALLOC_USAGE_HW_RENDER |
                                        GRALLOC_USAGE_HW_COMPOSER);
-    const auto& activeMode = mHwc.getActiveMode(displayId);
-    ui::Size limitedSize = limitFramebufferSize(activeMode->getWidth(), activeMode->getHeight());
+    const auto limitedSize = limitFramebufferSize(size);
     mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
     mConsumer->setMaxAcquiredBufferCount(
             SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
 }
 
-void FramebufferSurface::resizeBuffers(uint32_t width, uint32_t height) {
-    ui::Size limitedSize = limitFramebufferSize(width, height);
+void FramebufferSurface::resizeBuffers(const ui::Size& newSize) {
+    const auto limitedSize = limitFramebufferSize(newSize);
     mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
 }
 
@@ -181,24 +179,24 @@
     }
 }
 
-ui::Size FramebufferSurface::limitFramebufferSize(uint32_t width, uint32_t height) {
-    ui::Size framebufferSize(width, height);
-    bool wasLimited = true;
-    if (width > mMaxWidth && mMaxWidth != 0) {
-        float aspectRatio = float(width) / float(height);
-        framebufferSize.height = mMaxWidth / aspectRatio;
-        framebufferSize.width = mMaxWidth;
+ui::Size FramebufferSurface::limitFramebufferSize(const ui::Size& size) {
+    ui::Size limitedSize = size;
+    bool wasLimited = false;
+    if (size.width > mMaxSize.width && mMaxSize.width != 0) {
+        const float aspectRatio = static_cast<float>(size.width) / size.height;
+        limitedSize.height = mMaxSize.width / aspectRatio;
+        limitedSize.width = mMaxSize.width;
         wasLimited = true;
     }
-    if (height > mMaxHeight && mMaxHeight != 0) {
-        float aspectRatio = float(width) / float(height);
-        framebufferSize.height = mMaxHeight;
-        framebufferSize.width = mMaxHeight * aspectRatio;
+    if (size.height > mMaxSize.height && mMaxSize.height != 0) {
+        const float aspectRatio = static_cast<float>(size.width) / size.height;
+        limitedSize.height = mMaxSize.height;
+        limitedSize.width = mMaxSize.height * aspectRatio;
         wasLimited = true;
     }
     ALOGI_IF(wasLimited, "framebuffer size has been limited to [%dx%d] from [%dx%d]",
-             framebufferSize.width, framebufferSize.height, width, height);
-    return framebufferSize;
+             limitedSize.width, limitedSize.height, size.width, size.height);
+    return limitedSize;
 }
 
 void FramebufferSurface::dumpAsString(String8& result) const {
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 759943a..5d1e131 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -41,8 +41,8 @@
 class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface {
 public:
     FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
-                       const sp<IGraphicBufferConsumer>& consumer, uint32_t maxWidth,
-                       uint32_t maxHeight);
+                       const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
+                       const ui::Size& maxSize);
 
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
@@ -50,7 +50,7 @@
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
 
-    virtual void resizeBuffers(uint32_t width, uint32_t height);
+    virtual void resizeBuffers(const ui::Size&) override;
 
     virtual const sp<Fence>& getClientTargetAcquireFence() const override;
 
@@ -62,7 +62,7 @@
     virtual void dumpLocked(String8& result, const char* prefix) const;
 
     // Limits the width and height by the maximum width specified in the constructor.
-    ui::Size limitFramebufferSize(uint32_t width, uint32_t height);
+    ui::Size limitFramebufferSize(const ui::Size&);
 
     // nextBuffer waits for and then latches the next buffer from the
     // BufferQueue and releases the previously latched buffer to the
@@ -74,11 +74,7 @@
 
     // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
     // the device.
-    const uint32_t mMaxWidth;
-
-    // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
-    // the device.
-    const uint32_t mMaxHeight;
+    const ui::Size mMaxSize;
 
     // mCurrentBufferIndex is the slot index of the current buffer or
     // INVALID_BUFFER_SLOT to indicate that either there is no current buffer
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 46dc54e..b9a8e4b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -223,8 +223,6 @@
                  __FUNCTION__, to_string(*displayId).c_str());
 
     {
-        std::lock_guard lock(displayData.lastHwVsyncLock);
-
         // There have been reports of HWCs that signal several vsync events
         // with the same timestamp when turning the display off and on. This
         // is a bug in the HWC implementation, but filter the extra events
@@ -295,11 +293,10 @@
                                                   hal::DisplayType::PHYSICAL);
     newDisplay->setConnected(true);
     displayData.hwcDisplay = std::move(newDisplay);
-    loadModes(displayData, hwcDisplayId);
 }
 
 int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
-                                 hal::Attribute attribute) {
+                                 hal::Attribute attribute) const {
     int32_t value = 0;
     auto error = static_cast<hal::Error>(
             mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
@@ -308,30 +305,6 @@
     return value;
 }
 
-void HWComposer::loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId) {
-    ALOGV("[HWC display %" PRIu64 "] %s", hwcDisplayId, __FUNCTION__);
-
-    std::vector<hal::HWConfigId> configIds;
-    auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
-    RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId));
-
-    displayData.modes.clear();
-    for (auto configId : configIds) {
-        auto mode = DisplayMode::Builder(configId)
-                            .setId(DisplayModeId(displayData.modes.size()))
-                            .setWidth(getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH))
-                            .setHeight(getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT))
-                            .setVsyncPeriod(getAttribute(hwcDisplayId, configId,
-                                                         hal::Attribute::VSYNC_PERIOD))
-                            .setDpiX(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X))
-                            .setDpiY(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y))
-                            .setConfigGroup(getAttribute(hwcDisplayId, configId,
-                                                         hal::Attribute::CONFIG_GROUP))
-                            .build();
-        displayData.modes.push_back(std::move(mode));
-    }
-}
-
 HWC2::Layer* HWComposer::createLayer(HalDisplayId displayId) {
     RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
 
@@ -348,55 +321,50 @@
     RETURN_IF_HWC_ERROR(error, displayId);
 }
 
-nsecs_t HWComposer::getRefreshTimestamp(PhysicalDisplayId displayId) const {
-    RETURN_IF_INVALID_DISPLAY(displayId, 0);
-    const auto& displayData = mDisplayData.at(displayId);
-    // this returns the last refresh timestamp.
-    // if the last one is not available, we estimate it based on
-    // the refresh period and whatever closest timestamp we have.
-    std::lock_guard lock(displayData.lastHwVsyncLock);
-    nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
-    return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
-}
-
 bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
     RETURN_IF_INVALID_DISPLAY(displayId, false);
     return mDisplayData.at(displayId).hwcDisplay->isConnected();
 }
 
-DisplayModes HWComposer::getModes(PhysicalDisplayId displayId) const {
+std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const {
     RETURN_IF_INVALID_DISPLAY(displayId, {});
 
-    // We cache the modes when the DisplayData is created on hotplug. If the modes need to
-    // change HWC will send a hotplug event which will recreate displayData.
-    return mDisplayData.at(displayId).modes;
+    const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
+    std::vector<hal::HWConfigId> configIds;
+    auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
+    RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
+
+    std::vector<HWCDisplayMode> modes;
+    modes.reserve(configIds.size());
+    for (auto configId : configIds) {
+        modes.push_back(HWCDisplayMode{
+                .hwcId = configId,
+                .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
+                .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
+                .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
+                .dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X),
+                .dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y),
+                .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
+        });
+    }
+
+    return modes;
 }
 
-DisplayModePtr HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
-    RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
+std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
+    RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
 
     const auto hwcId = *fromPhysicalDisplayId(displayId);
     ALOGV("[%" PRIu64 "] getActiveMode", hwcId);
     hal::HWConfigId configId;
     auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
 
-    const auto& modes = mDisplayData.at(displayId).modes;
     if (error == hal::Error::BAD_CONFIG) {
         LOG_DISPLAY_ERROR(displayId, "No active mode");
-        return nullptr;
+        return std::nullopt;
     }
 
-    RETURN_IF_HWC_ERROR(error, displayId, nullptr);
-
-    const auto it = std::find_if(modes.begin(), modes.end(),
-                                 [configId](auto mode) { return mode->getHwcId() == configId; });
-    if (it == modes.end()) {
-        LOG_DISPLAY_ERROR(displayId, "Unknown mode");
-        return nullptr;
-    }
-
-    return *it;
+    return configId;
 }
 
 // Composer 2.4
@@ -421,27 +389,20 @@
     return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
 }
 
-nsecs_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId) const {
+status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+                                           nsecs_t* outVsyncPeriod) const {
     RETURN_IF_INVALID_DISPLAY(displayId, 0);
 
-    if (isVsyncPeriodSwitchSupported(displayId)) {
-        const auto hwcId = *fromPhysicalDisplayId(displayId);
-        Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
-        auto error =
-                static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
-        RETURN_IF_HWC_ERROR(error, displayId, 0);
-        return static_cast<nsecs_t>(vsyncPeriodNanos);
+    if (!isVsyncPeriodSwitchSupported(displayId)) {
+        return INVALID_OPERATION;
     }
-
-    // Get the default vsync period
-    auto mode = getActiveMode(displayId);
-
-    if (!mode) {
-        // HWC has updated the display modes and hasn't notified us yet.
-        RETURN_IF_HWC_ERROR(hal::Error::BAD_CONFIG, displayId, 0);
-    }
-
-    return mode->getVsyncPeriod();
+    const auto hwcId = *fromPhysicalDisplayId(displayId);
+    Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
+    auto error =
+            static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
+    RETURN_IF_HWC_ERROR(error, displayId, 0);
+    *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
+    return NO_ERROR;
 }
 
 std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 1ffe276..f9c8e2e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -83,6 +83,16 @@
         ClientTargetProperty clientTargetProperty;
     };
 
+    struct HWCDisplayMode {
+        hal::HWConfigId hwcId;
+        int32_t width = -1;
+        int32_t height = -1;
+        nsecs_t vsyncPeriod = -1;
+        int32_t dpiX = -1;
+        int32_t dpiY = -1;
+        int32_t configGroup = -1;
+    };
+
     virtual ~HWComposer();
 
     virtual void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
@@ -182,12 +192,11 @@
     virtual bool onVsync(hal::HWDisplayId, int64_t timestamp) = 0;
     virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;
 
-    virtual nsecs_t getRefreshTimestamp(PhysicalDisplayId) const = 0;
     virtual bool isConnected(PhysicalDisplayId) const = 0;
 
-    virtual DisplayModes getModes(PhysicalDisplayId) const = 0;
+    virtual std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const = 0;
 
-    virtual DisplayModePtr getActiveMode(PhysicalDisplayId) const = 0;
+    virtual std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const = 0;
 
     virtual std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const = 0;
 
@@ -197,7 +206,8 @@
     // Composer 2.4
     virtual DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0;
     virtual bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const = 0;
-    virtual nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId) const = 0;
+    virtual status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+                                           nsecs_t* outVsyncPeriod) const = 0;
     virtual status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
                                                   const hal::VsyncPeriodChangeConstraints&,
                                                   hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
@@ -314,12 +324,11 @@
     bool onVsync(hal::HWDisplayId, int64_t timestamp) override;
     void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;
 
-    nsecs_t getRefreshTimestamp(PhysicalDisplayId) const override;
     bool isConnected(PhysicalDisplayId) const override;
 
-    DisplayModes getModes(PhysicalDisplayId) const override;
+    std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const override;
 
-    DisplayModePtr getActiveMode(PhysicalDisplayId) const override;
+    std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const override;
 
     std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const override;
 
@@ -328,7 +337,8 @@
     // Composer 2.4
     DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override;
     bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const override;
-    nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId displayId) const override;
+    status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+                                   nsecs_t* outVsyncPeriod) const override;
     status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
                                           const hal::VsyncPeriodChangeConstraints&,
                                           hal::VsyncPeriodChangeTimeline* outTimeline) override;
@@ -365,7 +375,6 @@
         std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
         buffer_handle_t outbufHandle = nullptr;
         sp<Fence> outbufAcquireFence = Fence::NO_FENCE;
-        DisplayModes modes;
 
         bool validateWasSkipped;
         hal::Error presentError;
@@ -375,8 +384,7 @@
         std::mutex vsyncEnabledLock;
         hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
 
-        mutable std::mutex lastHwVsyncLock;
-        nsecs_t lastHwVsync GUARDED_BY(lastHwVsyncLock) = 0;
+        nsecs_t lastHwVsync = 0;
     };
 
     std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
@@ -384,8 +392,7 @@
     bool shouldIgnoreHotplugConnect(hal::HWDisplayId, bool hasDisplayIdentificationData) const;
 
     int32_t getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
-                         hal::Attribute attribute);
-    void loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId);
+                         hal::Attribute attribute) const;
 
     void loadCapabilities();
     void loadLayerMetadataSupport();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 2ac67cb..e26ab11 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -291,11 +291,11 @@
 void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
 }
 
-void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
-    mQueueBufferOutput.width = w;
-    mQueueBufferOutput.height = h;
-    mSinkBufferWidth = w;
-    mSinkBufferHeight = h;
+void VirtualDisplaySurface::resizeBuffers(const ui::Size& newSize) {
+    mQueueBufferOutput.width = newSize.width;
+    mQueueBufferOutput.height = newSize.height;
+    mSinkBufferWidth = newSize.width;
+    mSinkBufferHeight = newSize.height;
 }
 
 const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index fba0e3b..bbb6306 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -90,7 +90,7 @@
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
-    virtual void resizeBuffers(const uint32_t w, const uint32_t h);
+    virtual void resizeBuffers(const ui::Size&) override;
     virtual const sp<Fence>& getClientTargetAcquireFence() const override;
 
 private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a63a3d7..6b78627 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -68,6 +68,7 @@
 #include <ui/ColorSpace.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayConfig.h>
+#include <ui/DisplayId.h>
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayStatInfo.h>
 #include <ui/DisplayState.h>
@@ -1586,12 +1587,11 @@
 }
 
 nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
-    const auto displayId = getInternalDisplayIdLocked();
-    if (!displayId || !getHwComposer().isConnected(*displayId)) {
-        return 0;
+    if (const auto display = getDefaultDisplayDeviceLocked()) {
+        return display->getVsyncPeriodFromHWC();
     }
 
-    return getHwComposer().getDisplayVsyncPeriod(*displayId);
+    return 0;
 }
 
 void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
@@ -1605,6 +1605,12 @@
         return;
     }
 
+    if (const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId)) {
+        auto token = getPhysicalDisplayTokenLocked(*displayId);
+        auto display = getDisplayDeviceLocked(token);
+        display->onVsync(timestamp);
+    }
+
     if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {
         return;
     }
@@ -2223,8 +2229,7 @@
         } else if (isDisplayConnected) {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
-            const nsecs_t presentTime =
-                    getHwComposer().getRefreshTimestamp(display->getPhysicalId());
+            const nsecs_t presentTime = display->getRefreshTimestamp();
             mAnimFrameTracker.setActualPresentTime(presentTime);
         }
         mAnimFrameTracker.advanceFrame();
@@ -2361,6 +2366,24 @@
     // here the transaction has been committed
 }
 
+DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId displayId) const {
+    const auto hwcModes = getHwComposer().getModes(displayId);
+    DisplayModes modes;
+    size_t nextModeId = 0;
+    for (const auto& hwcMode : hwcModes) {
+        modes.push_back(DisplayMode::Builder(hwcMode.hwcId)
+                                .setId(DisplayModeId{nextModeId++})
+                                .setWidth(hwcMode.width)
+                                .setHeight(hwcMode.height)
+                                .setVsyncPeriod(hwcMode.vsyncPeriod)
+                                .setDpiX(hwcMode.dpiX)
+                                .setDpiY(hwcMode.dpiY)
+                                .setConfigGroup(hwcMode.configGroup)
+                                .build());
+    }
+    return modes;
+}
+
 void SurfaceFlinger::processDisplayHotplugEventsLocked() {
     for (const auto& event : mPendingHotplugEvents) {
         std::optional<DisplayIdentificationInfo> info =
@@ -2374,8 +2397,14 @@
         const auto it = mPhysicalDisplayTokens.find(displayId);
 
         if (event.connection == hal::Connection::CONNECTED) {
-            auto supportedModes = getHwComposer().getModes(displayId);
-            const auto activeMode = getHwComposer().getActiveMode(displayId);
+            auto supportedModes = loadSupportedDisplayModes(displayId);
+            const auto activeModeHwcId = getHwComposer().getActiveMode(displayId);
+            LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active config");
+
+            const auto activeMode = *std::find_if(supportedModes.begin(), supportedModes.end(),
+                                                  [activeModeHwcId](const DisplayModePtr& mode) {
+                                                      return mode->getHwcId() == *activeModeHwcId;
+                                                  });
             // TODO(b/175678215) Handle the case when activeMode is not in supportedModes
 
             if (it == mPhysicalDisplayTokens.end()) {
@@ -2526,17 +2555,15 @@
 
 void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
                                          const DisplayDeviceState& state) {
-    int width = 0;
-    int height = 0;
+    ui::Size resolution(0, 0);
     ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
     if (state.physical) {
-        width = state.physical->activeMode->getWidth();
-        height = state.physical->activeMode->getHeight();
+        resolution = state.physical->activeMode->getSize();
         pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
     } else if (state.surface != nullptr) {
-        int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
+        int status = state.surface->query(NATIVE_WINDOW_WIDTH, &resolution.width);
         ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
-        status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
+        status = state.surface->query(NATIVE_WINDOW_HEIGHT, &resolution.height);
         ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
         int intPixelFormat;
         status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
@@ -2553,7 +2580,7 @@
     if (const auto& physical = state.physical) {
         builder.setPhysical({physical->id, physical->type});
     }
-    builder.setPixels(ui::Size(width, height));
+    builder.setPixels(resolution);
     builder.setPixelFormat(pixelFormat);
     builder.setIsSecure(state.isSecure);
     builder.setLayerStackId(state.layerStack);
@@ -2588,7 +2615,8 @@
         const auto physicalId = PhysicalDisplayId::tryCast(displayId);
         LOG_FATAL_IF(!physicalId);
         displaySurface = new FramebufferSurface(getHwComposer(), *physicalId, bqConsumer,
-                                                maxGraphicsWidth, maxGraphicsHeight);
+                                                state.physical->activeMode->getSize(),
+                                                ui::Size(maxGraphicsWidth, maxGraphicsHeight));
         producer = bqProducer;
     }
 
@@ -4843,15 +4871,12 @@
                   "  gpu_to_cpu_unsupported    : %d\n",
                   mTransactionFlags.load(), !mGpuToCpuSupported);
 
-    if (const auto displayId = getInternalDisplayIdLocked();
-        displayId && getHwComposer().isConnected(*displayId)) {
-        const auto activeConfig = getHwComposer().getActiveMode(*displayId);
+    if (const auto display = getDefaultDisplayDeviceLocked()) {
         std::string fps, xDpi, yDpi;
-        if (activeConfig) {
-            const auto vsyncPeriod = getHwComposer().getDisplayVsyncPeriod(*displayId);
-            fps = base::StringPrintf("%s", to_string(Fps::fromPeriodNsecs(vsyncPeriod)).c_str());
-            xDpi = base::StringPrintf("%.2f", activeConfig->getDpiX());
-            yDpi = base::StringPrintf("%.2f", activeConfig->getDpiY());
+        if (const auto activeMode = display->getActiveMode()) {
+            fps = to_string(activeMode->getFps());
+            xDpi = base::StringPrintf("%.2f", activeMode->getDpiX());
+            yDpi = base::StringPrintf("%.2f", activeMode->getDpiY());
         } else {
             fps = "unknown";
             xDpi = "unknown";
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ec73b09..5b2d1c3 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -897,6 +897,7 @@
     /*
      * Display management
      */
+    DisplayModes loadSupportedDisplayModes(PhysicalDisplayId) const;
     sp<DisplayDevice> setupNewDisplayDeviceInternal(
             const wp<IBinder>& displayToken,
             std::shared_ptr<compositionengine::Display> compositionDisplay,
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index bd49728..e0cb7c8 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -63,9 +63,7 @@
 
 // Mock test helpers
 using ::testing::_;
-using ::testing::AtLeast;
 using ::testing::DoAll;
-using ::testing::Invoke;
 using ::testing::Return;
 using ::testing::SetArgPointee;
 
@@ -74,9 +72,11 @@
 using Display = V2_1::Display;
 
 ///////////////////////////////////////////////
-
-constexpr PhysicalDisplayId kPrimaryDisplayId = PhysicalDisplayId::fromPort(PRIMARY_DISPLAY);
-constexpr PhysicalDisplayId kExternalDisplayId = PhysicalDisplayId::fromPort(EXTERNAL_DISPLAY);
+constexpr PhysicalDisplayId physicalIdFromHwcDisplayId(Display hwcId) {
+    return PhysicalDisplayId::fromPort(hwcId);
+}
+constexpr PhysicalDisplayId kPrimaryDisplayId = physicalIdFromHwcDisplayId(PRIMARY_DISPLAY);
+constexpr PhysicalDisplayId kExternalDisplayId = physicalIdFromHwcDisplayId(EXTERNAL_DISPLAY);
 
 struct TestColor {
 public:
@@ -158,7 +158,7 @@
                 self->mReceivedDisplayEvents.push_back(buffer[i]);
             }
         }
-        ALOGD_IF(n < 0, "Error reading events (%s)\n", strerror(-n));
+        ALOGD_IF(n < 0, "Error reading events (%s)", strerror(-n));
         return 1;
     }
 
@@ -174,7 +174,7 @@
     void setExpectationsForConfigs(Display display, std::vector<TestConfig> testConfigs,
                                    Config activeConfig, V2_4::VsyncPeriodNanos defaultVsyncPeriod) {
         std::vector<Config> configIds;
-        for (int i = 0; i < testConfigs.size(); i++) {
+        for (size_t i = 0; i < testConfigs.size(); i++) {
             configIds.push_back(testConfigs[i].id);
 
             EXPECT_CALL(*mMockComposer,
@@ -269,10 +269,10 @@
         mMockComposer = nullptr;
     }
 
-    void waitForDisplayTransaction() {
+    void waitForDisplayTransaction(Display display) {
         // Both a refresh and a vsync event are needed to apply pending display
         // transactions.
-        mFakeComposerClient->refreshDisplay(EXTERNAL_DISPLAY);
+        mFakeComposerClient->refreshDisplay(display);
         mFakeComposerClient->runVSyncAndWait();
 
         // Extra vsync and wait to avoid a 10% flake due to a race.
@@ -291,7 +291,7 @@
                 mReceivedDisplayEvents.pop_front();
 
                 ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
-                         "event hotplug: displayId %s, connected %d\t",
+                         "event hotplug: displayId %s, connected %d",
                          to_string(event.header.displayId).c_str(), event.hotplug.connected);
 
                 if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG &&
@@ -314,7 +314,7 @@
                 mReceivedDisplayEvents.pop_front();
 
                 ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED,
-                         "event config: displayId %s, configId %d\t",
+                         "event config: displayId %s, configId %d",
                          to_string(event.header.displayId).c_str(), event.config.configId);
 
                 if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
@@ -341,7 +341,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
         {
@@ -372,7 +372,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         mFakeComposerClient->clearFrames();
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
 
@@ -403,7 +403,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
         const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -456,7 +456,7 @@
                                                                               config.refreshRate,
                                                                               config.refreshRate,
                                                                               config.refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -487,7 +487,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         mFakeComposerClient->clearFrames();
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
     }
@@ -510,7 +510,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
         const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -562,7 +562,7 @@
                                                                               config.refreshRate,
                                                                               config.refreshRate,
                                                                               config.refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -593,7 +593,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         mFakeComposerClient->clearFrames();
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
     }
@@ -626,7 +626,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
         const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -669,7 +669,7 @@
                     .WillOnce(Return(V2_1::Error::NONE));
         }
 
-        for (int i = 0; i < configs.size(); i++) {
+        for (size_t i = 0; i < configs.size(); i++) {
             const auto& config = configs[i];
             if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) {
                 EXPECT_EQ(NO_ERROR,
@@ -679,7 +679,7 @@
                                                                configs[i].refreshRate,
                                                                configs[i].refreshRate,
                                                                configs[i].refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -726,7 +726,7 @@
                                                                               config.refreshRate,
                                                                               config.refreshRate,
                                                                               config.refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -773,7 +773,7 @@
                                                                               config.refreshRate,
                                                                               config.refreshRate,
                                                                               config.refreshRate));
-                waitForDisplayTransaction();
+                waitForDisplayTransaction(EXTERNAL_DISPLAY);
                 EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
                 break;
             }
@@ -804,7 +804,7 @@
 
         mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(EXTERNAL_DISPLAY);
         mFakeComposerClient->clearFrames();
         EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
     }
@@ -815,7 +815,7 @@
         mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
                                             V2_1::IComposerCallback::Connection::DISCONNECTED);
 
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(PRIMARY_DISPLAY);
 
         EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, false));
         {
@@ -840,7 +840,7 @@
         mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
                                             V2_1::IComposerCallback::Connection::CONNECTED);
 
-        waitForDisplayTransaction();
+        waitForDisplayTransaction(PRIMARY_DISPLAY);
 
         EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, true));
 
@@ -856,6 +856,121 @@
         }
     }
 
+    void Test_SubsequentHotplugConnectUpdatesDisplay(Display hwcDisplayId) {
+        ALOGD("DisplayTest::Test_SubsequentHotplugConnectUpdatesDisplay");
+
+        // Send a hotplug connected event to set up the initial display modes.
+        // The primary display is already connected so this will update it.
+        // If we're running the test of an external display this will create it.
+        setExpectationsForConfigs(hwcDisplayId,
+                                  {{.id = 1,
+                                    .w = 800,
+                                    .h = 1600,
+                                    .vsyncPeriod = 11'111'111,
+                                    .group = 1}},
+                                  /* activeConfig */ 1, 11'111'111);
+
+        mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+                                            V2_1::IComposerCallback::Connection::CONNECTED);
+        waitForDisplayTransaction(hwcDisplayId);
+        EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+        const auto displayId = physicalIdFromHwcDisplayId(hwcDisplayId);
+        const auto display = SurfaceComposerClient::getPhysicalDisplayToken(displayId);
+        EXPECT_FALSE(display == nullptr);
+
+        // Verify that the active mode and the supported moded are updated
+        {
+            DisplayConfig config;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+            EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+            EXPECT_EQ(1e9f / 11'111'111, config.refreshRate);
+
+            Vector<DisplayConfig> configs;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+            EXPECT_EQ(configs.size(), 1);
+        }
+
+        // Send another hotplug connected event
+        setExpectationsForConfigs(hwcDisplayId,
+                                  {
+                                          {.id = 1,
+                                           .w = 800,
+                                           .h = 1600,
+                                           .vsyncPeriod = 16'666'666,
+                                           .group = 1},
+                                          {.id = 2,
+                                           .w = 800,
+                                           .h = 1600,
+                                           .vsyncPeriod = 11'111'111,
+                                           .group = 1},
+                                          {.id = 3,
+                                           .w = 800,
+                                           .h = 1600,
+                                           .vsyncPeriod = 8'333'333,
+                                           .group = 1},
+                                  },
+                                  /* activeConfig */ 1, 16'666'666);
+
+        mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+                                            V2_1::IComposerCallback::Connection::CONNECTED);
+        waitForDisplayTransaction(hwcDisplayId);
+        EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+        // Verify that the active mode and the supported moded are updated
+        {
+            DisplayConfig config;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+            EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+            EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+        }
+
+        Vector<DisplayConfig> configs;
+        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+        EXPECT_EQ(configs.size(), 3);
+
+        EXPECT_EQ(ui::Size(800, 1600), configs[0].resolution);
+        EXPECT_EQ(1e9f / 16'666'666, configs[0].refreshRate);
+
+        EXPECT_EQ(ui::Size(800, 1600), configs[1].resolution);
+        EXPECT_EQ(1e9f / 11'111'111, configs[1].refreshRate);
+
+        EXPECT_EQ(ui::Size(800, 1600), configs[2].resolution);
+        EXPECT_EQ(1e9f / 8'333'333, configs[2].refreshRate);
+
+        // Verify that we are able to switch to any of the modes
+        for (int i = configs.size() - 1; i >= 0; i--) {
+            const auto hwcId = i + 1;
+            // Set up HWC expectations for the mode change
+            if (mIs2_4Client) {
+                EXPECT_CALL(*mMockComposer,
+                            setActiveConfigWithConstraints(hwcDisplayId, hwcId, _, _))
+                        .WillOnce(Return(V2_4::Error::NONE));
+            } else {
+                EXPECT_CALL(*mMockComposer, setActiveConfig(hwcDisplayId, hwcId))
+                        .WillOnce(Return(V2_1::Error::NONE));
+            }
+
+            EXPECT_EQ(NO_ERROR,
+                      SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false,
+                                                                          configs[i].refreshRate,
+                                                                          configs[i].refreshRate,
+                                                                          configs[i].refreshRate,
+                                                                          configs[i].refreshRate));
+            // We need to refresh twice - once to apply the pending mode change request,
+            // and once to process the change.
+            waitForDisplayTransaction(hwcDisplayId);
+            waitForDisplayTransaction(hwcDisplayId);
+            EXPECT_TRUE(waitForConfigChangedEvent(hwcDisplayId, i))
+                    << "Failure while switching to mode " << i;
+
+            DisplayConfig config;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+            EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+            EXPECT_EQ(configs[i].refreshRate, config.refreshRate);
+        }
+    }
+
     sp<V2_1::IComposer> mFakeService;
     sp<SurfaceComposerClient> mComposerClient;
 
@@ -911,6 +1026,14 @@
     Test_HotplugPrimaryDisplay();
 }
 
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesExternalDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
 using DisplayTest_2_2 = DisplayTest<FakeComposerService_2_2>;
 
 TEST_F(DisplayTest_2_2, HotplugOneConfig) {
@@ -933,6 +1056,14 @@
     Test_HotplugPrimaryDisplay();
 }
 
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesExternalDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
 using DisplayTest_2_3 = DisplayTest<FakeComposerService_2_3>;
 
 TEST_F(DisplayTest_2_3, HotplugOneConfig) {
@@ -955,6 +1086,14 @@
     Test_HotplugPrimaryDisplay();
 }
 
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesExternalDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
 using DisplayTest_2_4 = DisplayTest<FakeComposerService_2_4>;
 
 TEST_F(DisplayTest_2_4, HotplugOneConfig) {
@@ -977,6 +1116,14 @@
     Test_HotplugPrimaryDisplay();
 }
 
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesExternalDisplay) {
+    Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
 ////////////////////////////////////////////////
 
 template <typename FakeComposerService>
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f2051d9..b696a6d 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -62,15 +62,9 @@
 
 using testing::_;
 using testing::AtLeast;
-using testing::Between;
-using testing::ByMove;
 using testing::DoAll;
-using testing::Field;
-using testing::Invoke;
 using testing::IsNull;
 using testing::Mock;
-using testing::NotNull;
-using testing::Ref;
 using testing::Return;
 using testing::ReturnRef;
 using testing::SetArgPointee;
@@ -86,7 +80,6 @@
 constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
 constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
 
-constexpr int DEFAULT_CONFIG_ID = 0;
 constexpr int DEFAULT_TEXTURE_ID = 6000;
 constexpr int DEFAULT_LAYER_STACK = 7000;
 
@@ -147,7 +140,7 @@
 
         EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
         EXPECT_CALL(*vsyncTracker, currentPeriod())
-                .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+                .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
         EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
 
         constexpr ISchedulerCallback* kCallback = nullptr;
@@ -548,12 +541,6 @@
         setupLatchedBuffer(test, layer);
     }
 
-    static void setupBufferLayerPostFrameCallExpectations(CompositionTest* test) {
-        // BufferLayer::onPostComposition(), when there is no present fence
-        EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY, _))
-                .WillOnce(DoAll(SetArgPointee<1>(DEFAULT_CONFIG_ID), Return(Error::NONE)));
-    }
-
     static void setupHwcSetGeometryCallExpectations(CompositionTest* test) {
         if (!test->mDisplayOff) {
             // TODO: Coverage of other values
@@ -632,8 +619,6 @@
                     .Times(1);
             EXPECT_CALL(*test->mComposer, setLayerBuffer(HWC_DISPLAY, HWC_LAYER, _, _, _)).Times(1);
         }
-
-        setupBufferLayerPostFrameCallExpectations(test);
     }
 
     static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) {
@@ -793,7 +778,6 @@
 
     static void setupInsecureREBufferCompositionCallExpectations(CompositionTest* test) {
         setupInsecureREBufferCompositionCommonCallExpectations(test);
-        Base::setupBufferLayerPostFrameCallExpectations(test);
     }
 
     static void setupInsecureREBufferScreenshotCompositionCallExpectations(CompositionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 1e24c0a..6b82170 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -175,90 +175,5 @@
     EXPECT_EQ(hal::Error::UNSUPPORTED, result);
 }
 
-class HWComposerConfigsTest : public testing::Test {
-public:
-    Hwc2::mock::Composer* mHal = new StrictMock<Hwc2::mock::Composer>();
-    MockHWC2ComposerCallback mCallback;
-
-    void setActiveConfig(Config config) {
-        EXPECT_CALL(*mHal, getActiveConfig(_, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(config), Return(V2_1::Error::NONE)));
-    }
-
-    void setDisplayConfigs(std::vector<Config> configs) {
-        EXPECT_CALL(*mHal, getDisplayConfigs(_, _))
-                .WillOnce(DoAll(SetArgPointee<1>(configs), Return(V2_1::Error::NONE)));
-        EXPECT_CALL(*mHal, getDisplayAttribute(_, _, _, _))
-                .WillRepeatedly(DoAll(SetArgPointee<3>(1), Return(V2_1::Error::NONE)));
-    }
-
-    void testSetActiveModeWithConstraintsCommon(bool isVsyncPeriodSwitchSupported);
-};
-
-void HWComposerConfigsTest::testSetActiveModeWithConstraintsCommon(
-        bool isVsyncPeriodSwitchSupported) {
-    EXPECT_CALL(*mHal, getMaxVirtualDisplayCount()).WillOnce(Return(0));
-    EXPECT_CALL(*mHal, getCapabilities()).WillOnce(Return(std::vector<hal::Capability>{}));
-    EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_)).WillOnce(Return(V2_4::Error::UNSUPPORTED));
-    EXPECT_CALL(*mHal, registerCallback(_));
-    EXPECT_CALL(*mHal, setVsyncEnabled(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
-    EXPECT_CALL(*mHal, getDisplayIdentificationData(_, _, _))
-            .WillRepeatedly(Return(V2_1::Error::UNSUPPORTED));
-    EXPECT_CALL(*mHal, setClientTargetSlotCount(_)).WillRepeatedly(Return(V2_1::Error::NONE));
-
-    EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported())
-            .WillRepeatedly(Return(isVsyncPeriodSwitchSupported));
-
-    if (isVsyncPeriodSwitchSupported) {
-        EXPECT_CALL(*mHal, setActiveConfigWithConstraints(_, _, _, _))
-                .WillRepeatedly(Return(V2_4::Error::NONE));
-    } else {
-        EXPECT_CALL(*mHal, setActiveConfig(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
-    }
-
-    impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
-    hwc.setConfiguration(&mCallback, 123);
-
-    setDisplayConfigs({15});
-    setActiveConfig(15);
-
-    const auto physicalId = PhysicalDisplayId::fromPort(0);
-    const hal::HWDisplayId hwcId = 0;
-    hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
-    hal::VsyncPeriodChangeConstraints constraints;
-    constraints.desiredTimeNanos = systemTime();
-    constraints.seamlessRequired = false;
-
-    hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
-    constexpr Config kConfigIndex = 0;
-    const auto status =
-            hwc.setActiveModeWithConstraints(physicalId, kConfigIndex, constraints, &timeline);
-    EXPECT_EQ(NO_ERROR, status);
-
-    const std::vector<Config> kConfigs{7, 8, 9, 10, 11};
-    // Change the set of supported modes.
-    setDisplayConfigs(kConfigs);
-    setActiveConfig(11);
-    hwc.onHotplug(hwcId, hal::Connection::CONNECTED);
-    hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
-    for (size_t configIndex = 0; configIndex < kConfigs.size(); configIndex++) {
-        const auto status =
-                hwc.setActiveModeWithConstraints(physicalId,
-                                                 static_cast<hal::HWConfigId>(configIndex),
-                                                 constraints, &timeline);
-        EXPECT_EQ(NO_ERROR, status) << "Error when switching to config " << configIndex;
-    }
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingSupported) {
-    testSetActiveModeWithConstraintsCommon(/*supported=*/true);
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingNotSupported) {
-    testSetActiveModeWithConstraintsCommon(/*supported=*/false);
-}
-
 } // namespace
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index c5deb7c..abecd4b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -144,7 +144,7 @@
 
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     EXPECT_CALL(*vsyncTracker, currentPeriod())
-            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
                             std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index e060df2..a6d07d0 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -185,7 +185,7 @@
 
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     EXPECT_CALL(*vsyncTracker, currentPeriod())
-            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
     EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
     mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
                             std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
index 8552e15..b713334 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
@@ -669,7 +669,7 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
+    EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(newWidth, oldHeight))).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
@@ -714,7 +714,7 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
+    EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(oldWidth, newHeight))).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
@@ -764,7 +764,7 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*displaySurface, resizeBuffers(kNewWidth, kNewHeight)).Times(1);
+    EXPECT_CALL(*displaySurface, resizeBuffers(kNewSize.getSize())).Times(1);
 
     // --------------------------------------------------------------------
     // Invocation
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 3be45e2..16a76c2 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -41,6 +41,7 @@
 #include "SurfaceFlingerDefaultFactory.h"
 #include "SurfaceInterceptor.h"
 #include "TestableScheduler.h"
+#include "mock/DisplayHardware/MockComposer.h"
 #include "mock/MockDisplayIdGenerator.h"
 #include "mock/MockFrameTimeline.h"
 #include "mock/MockFrameTracer.h"
@@ -477,7 +478,7 @@
         static constexpr hal::HWDisplayId DEFAULT_HWC_DISPLAY_ID = 1000;
         static constexpr int32_t DEFAULT_WIDTH = 1920;
         static constexpr int32_t DEFAULT_HEIGHT = 1280;
-        static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
+        static constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'666;
         static constexpr int32_t DEFAULT_CONFIG_GROUP = 7;
         static constexpr int32_t DEFAULT_DPI = 320;
         static constexpr hal::HWConfigId DEFAULT_ACTIVE_CONFIG = 0;
@@ -502,8 +503,8 @@
             return *this;
         }
 
-        auto& setRefreshRate(int32_t refreshRate) {
-            mRefreshRate = refreshRate;
+        auto& setVsyncPeriod(int32_t vsyncPeriod) {
+            mVsyncPeriod = vsyncPeriod;
             return *this;
         }
 
@@ -532,7 +533,12 @@
             return *this;
         }
 
-        void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
+        void inject(TestableSurfaceFlinger* flinger, Hwc2::mock::Composer* composer) {
+            using ::testing::_;
+            using ::testing::DoAll;
+            using ::testing::Return;
+            using ::testing::SetArgPointee;
+
             static const std::unordered_set<hal::Capability> defaultCapabilities;
             if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
 
@@ -547,15 +553,39 @@
             display->setPowerMode(mPowerMode);
             flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
 
-            auto config = DisplayMode::Builder(mActiveConfig)
-                                  .setWidth(mWidth)
-                                  .setHeight(mHeight)
-                                  .setVsyncPeriod(mRefreshRate)
-                                  .setDpiX(mDpiX)
-                                  .setDpiY(mDpiY)
-                                  .setConfigGroup(mConfigGroup)
-                                  .build();
-            flinger->mutableHwcDisplayData()[mDisplayId].modes.push_back(config);
+            EXPECT_CALL(*composer, getDisplayConfigs(mHwcDisplayId, _))
+                    .WillRepeatedly(
+                            DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{mActiveConfig}),
+                                  Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::WIDTH, _))
+                    .WillRepeatedly(DoAll(SetArgPointee<3>(mWidth), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::HEIGHT,
+                                            _))
+                    .WillRepeatedly(DoAll(SetArgPointee<3>(mHeight), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+                                            hal::Attribute::VSYNC_PERIOD, _))
+                    .WillRepeatedly(
+                            DoAll(SetArgPointee<3>(mVsyncPeriod), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_X, _))
+                    .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiX), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_Y, _))
+                    .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiY), Return(hal::Error::NONE)));
+
+            EXPECT_CALL(*composer,
+                        getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+                                            hal::Attribute::CONFIG_GROUP, _))
+                    .WillRepeatedly(
+                            DoAll(SetArgPointee<3>(mConfigGroup), Return(hal::Error::NONE)));
 
             if (mHwcDisplayType == hal::DisplayType::PHYSICAL) {
                 const auto physicalId = PhysicalDisplayId::tryCast(mDisplayId);
@@ -581,10 +611,10 @@
         hal::HWDisplayId mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID;
         int32_t mWidth = DEFAULT_WIDTH;
         int32_t mHeight = DEFAULT_HEIGHT;
-        int32_t mRefreshRate = DEFAULT_REFRESH_RATE;
+        int32_t mVsyncPeriod = DEFAULT_VSYNC_PERIOD;
         int32_t mDpiX = DEFAULT_DPI;
-        int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
         int32_t mDpiY = DEFAULT_DPI;
+        int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
         hal::HWConfigId mActiveConfig = DEFAULT_ACTIVE_CONFIG;
         hal::PowerMode mPowerMode = DEFAULT_POWER_MODE;
         const std::unordered_set<hal::Capability>* mCapabilities = nullptr;
@@ -602,6 +632,21 @@
                 mHwcDisplayId(hwcDisplayId) {
             mCreationArgs.connectionType = connectionType;
             mCreationArgs.isPrimary = isPrimary;
+
+            mActiveModeId = DisplayModeId(0);
+            DisplayModePtr activeMode =
+                    DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
+                            .setId(mActiveModeId)
+                            .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
+                            .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
+                            .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
+                            .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
+                            .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
+                            .setConfigGroup(0)
+                            .build();
+
+            DisplayModes modes{activeMode};
+            mCreationArgs.supportedModes = modes;
         }
 
         sp<IBinder> token() const { return mDisplayToken; }
@@ -624,6 +669,16 @@
 
         auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
 
+        auto& setActiveMode(DisplayModeId mode) {
+            mActiveModeId = mode;
+            return *this;
+        }
+
+        auto& setSupportedModes(DisplayModes mode) {
+            mCreationArgs.supportedModes = mode;
+            return *this;
+        }
+
         auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
             mCreationArgs.nativeWindow = nativeWindow;
             return *this;
@@ -676,6 +731,9 @@
             state.isSecure = mCreationArgs.isSecure;
 
             sp<DisplayDevice> device = new DisplayDevice(mCreationArgs);
+            if (!device->isVirtual()) {
+                device->setActiveMode(mActiveModeId);
+            }
             mFlinger.mutableDisplays().emplace(mDisplayToken, device);
             mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
             mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
@@ -692,6 +750,7 @@
         sp<BBinder> mDisplayToken = new BBinder();
         DisplayDeviceCreationArgs mCreationArgs;
         const std::optional<hal::HWDisplayId> mHwcDisplayId;
+        DisplayModeId mActiveModeId;
     };
 
 private:
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 6d2f672..1ae42e7 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -72,7 +72,7 @@
 
         EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
         EXPECT_CALL(*mVSyncTracker, currentPeriod())
-                .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+                .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
 
         mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),
                                 std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),