Introduce DynamicDisplayInfo

In this CL we introduce the getDynamicDisplayInfo call
on ISurfaceComposer which replaces the existing
 - getDisplayModes
 - getActiveDisplayMode
 - getColorModes
 - getActiveColorMode
 - getHdrCapabilities

This way all display properties can be queried atomically.

The current DisplayInfo class is moved to the androd::ui
namespace and it's renamed to StaticDisplayInfo.

ui::DisplayMode is now LightFlattenable and the mode ID is
int32_t instead of size_t in order to prevent serialization
problems.

Additionally we add the ID field to ui::DisplayMode. This
way we no longer need the supported display IDs to be
from 0 to N-1.

Bug: 159590486
Bug: 180539476
Test: presubmit, manually test that device boots
Change-Id: I52b170913ce47cb5df2e8417e6cc95d395df1fda
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 58d6582..3c53c02 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -28,7 +28,6 @@
 #include <gui/Surface.h>
 #include <private/gui/ComposerService.h>
 
-#include <ui/DisplayInfo.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
diff --git a/include/input/TouchVideoFrame.h b/include/input/TouchVideoFrame.h
index 4fa2f86..eda628e 100644
--- a/include/input/TouchVideoFrame.h
+++ b/include/input/TouchVideoFrame.h
@@ -57,7 +57,7 @@
 
     /**
      * Rotate the video frame.
-     * The rotation value is an enum from ui/DisplayInfo.h
+     * The rotation value is an enum from ui/Rotation.h
      */
     void rotate(int32_t orientation);
 
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
deleted file mode 120000
index 9a195ea..0000000
--- a/include/ui/DisplayInfo.h
+++ /dev/null
@@ -1 +0,0 @@
-../../libs/ui/include/ui/DisplayInfo.h
\ No newline at end of file
diff --git a/include/ui/StaticDisplayInfo.h b/include/ui/StaticDisplayInfo.h
new file mode 120000
index 0000000..c58aae3
--- /dev/null
+++ b/include/ui/StaticDisplayInfo.h
@@ -0,0 +1 @@
+../../libs/ui/include/ui/StaticDisplayInfo.h
\ No newline at end of file
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 762746c..2e4f858 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -36,11 +36,12 @@
 
 #include <system/graphics.h>
 
-#include <ui/DisplayInfo.h>
 #include <ui/DisplayMode.h>
 #include <ui/DisplayStatInfo.h>
 #include <ui/DisplayState.h>
+#include <ui/DynamicDisplayInfo.h>
 #include <ui/HdrCapabilities.h>
+#include <ui/StaticDisplayInfo.h>
 
 #include <utils/Log.h>
 
@@ -323,32 +324,26 @@
         return result;
     }
 
-    status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) override {
+    status_t getStaticDisplayInfo(const sp<IBinder>& display,
+                                  ui::StaticDisplayInfo* info) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
-        remote()->transact(BnSurfaceComposer::GET_DISPLAY_INFO, data, &reply);
+        remote()->transact(BnSurfaceComposer::GET_STATIC_DISPLAY_INFO, data, &reply);
         const status_t result = reply.readInt32();
         if (result != NO_ERROR) return result;
         return reply.read(*info);
     }
 
-    status_t getDisplayModes(const sp<IBinder>& display, Vector<ui::DisplayMode>* modes) override {
+    status_t getDynamicDisplayInfo(const sp<IBinder>& display,
+                                   ui::DynamicDisplayInfo* info) override {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
-        remote()->transact(BnSurfaceComposer::GET_DISPLAY_MODES, data, &reply);
+        remote()->transact(BnSurfaceComposer::GET_DYNAMIC_DISPLAY_INFO, data, &reply);
         const status_t result = reply.readInt32();
-        if (result == NO_ERROR) {
-            const size_t numModes = reply.readUint32();
-            modes->clear();
-            modes->resize(numModes);
-            for (size_t i = 0; i < numModes; i++) {
-                memcpy(&(modes->editItemAt(i)), reply.readInplace(sizeof(ui::DisplayMode)),
-                       sizeof(ui::DisplayMode));
-            }
-        }
-        return result;
+        if (result != NO_ERROR) return result;
+        return reply.read(*info);
     }
 
     status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) override {
@@ -365,44 +360,6 @@
         return result;
     }
 
-    int getActiveDisplayModeId(const sp<IBinder>& display) override {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeStrongBinder(display);
-        remote()->transact(BnSurfaceComposer::GET_ACTIVE_DISPLAY_MODE, data, &reply);
-        return reply.readInt32();
-    }
-
-    status_t getDisplayColorModes(const sp<IBinder>& display,
-                                  Vector<ColorMode>* outColorModes) override {
-        Parcel data, reply;
-        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        if (result != NO_ERROR) {
-            ALOGE("getDisplayColorModes failed to writeInterfaceToken: %d", result);
-            return result;
-        }
-        result = data.writeStrongBinder(display);
-        if (result != NO_ERROR) {
-            ALOGE("getDisplayColorModes failed to writeStrongBinder: %d", result);
-            return result;
-        }
-        result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_COLOR_MODES, data, &reply);
-        if (result != NO_ERROR) {
-            ALOGE("getDisplayColorModes failed to transact: %d", result);
-            return result;
-        }
-        result = static_cast<status_t>(reply.readInt32());
-        if (result == NO_ERROR) {
-            size_t numModes = reply.readUint32();
-            outColorModes->clear();
-            outColorModes->resize(numModes);
-            for (size_t i = 0; i < numModes; ++i) {
-                outColorModes->replaceAt(static_cast<ColorMode>(reply.readInt32()), i);
-            }
-        }
-        return result;
-    }
-
     status_t getDisplayNativePrimaries(const sp<IBinder>& display,
                                        ui::DisplayPrimaries& primaries) override {
         Parcel data, reply;
@@ -429,26 +386,6 @@
         return result;
     }
 
-    ColorMode getActiveColorMode(const sp<IBinder>& display) override {
-        Parcel data, reply;
-        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        if (result != NO_ERROR) {
-            ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result);
-            return static_cast<ColorMode>(result);
-        }
-        result = data.writeStrongBinder(display);
-        if (result != NO_ERROR) {
-            ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result);
-            return static_cast<ColorMode>(result);
-        }
-        result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply);
-        if (result != NO_ERROR) {
-            ALOGE("getActiveColorMode failed to transact: %d", result);
-            return static_cast<ColorMode>(result);
-        }
-        return static_cast<ColorMode>(reply.readInt32());
-    }
-
     status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -580,28 +517,6 @@
         return reply.readInt32();
     }
 
-    status_t getHdrCapabilities(const sp<IBinder>& display,
-                                HdrCapabilities* outCapabilities) const override {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        status_t result = data.writeStrongBinder(display);
-        if (result != NO_ERROR) {
-            ALOGE("getHdrCapabilities failed to writeStrongBinder: %d", result);
-            return result;
-        }
-        result = remote()->transact(BnSurfaceComposer::GET_HDR_CAPABILITIES,
-                data, &reply);
-        if (result != NO_ERROR) {
-            ALOGE("getHdrCapabilities failed to transact: %d", result);
-            return result;
-        }
-        result = reply.readInt32();
-        if (result == NO_ERROR) {
-            result = reply.read(*outCapabilities);
-        }
-        return result;
-    }
-
     status_t enableVSyncInjections(bool enable) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -881,9 +796,10 @@
         return error;
     }
 
-    status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t defaultMode,
-                                        bool allowGroupSwitching, float primaryRefreshRateMin,
-                                        float primaryRefreshRateMax, float appRequestRefreshRateMin,
+    status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                        ui::DisplayModeId defaultMode, bool allowGroupSwitching,
+                                        float primaryRefreshRateMin, float primaryRefreshRateMax,
+                                        float appRequestRefreshRateMin,
                                         float appRequestRefreshRateMax) override {
         Parcel data, reply;
         status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -938,7 +854,8 @@
         return reply.readInt32();
     }
 
-    status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t* outDefaultMode,
+    status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                        ui::DisplayModeId* outDefaultMode,
                                         bool* outAllowGroupSwitching,
                                         float* outPrimaryRefreshRateMin,
                                         float* outPrimaryRefreshRateMax,
@@ -966,17 +883,16 @@
             ALOGE("getDesiredDisplayModeSpecs failed to transact: %d", result);
             return result;
         }
-        int32_t defaultMode;
-        result = reply.readInt32(&defaultMode);
+
+        result = reply.readInt32(outDefaultMode);
         if (result != NO_ERROR) {
             ALOGE("getDesiredDisplayModeSpecs failed to read defaultMode: %d", result);
             return result;
         }
-        if (defaultMode < 0) {
-            ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, defaultMode);
+        if (*outDefaultMode < 0) {
+            ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, *outDefaultMode);
             return BAD_VALUE;
         }
-        *outDefaultMode = static_cast<size_t>(defaultMode);
 
         result = reply.readBool(outAllowGroupSwitching);
         if (result != NO_ERROR) {
@@ -1436,28 +1352,24 @@
             }
             return NO_ERROR;
         }
-        case GET_DISPLAY_INFO: {
+        case GET_STATIC_DISPLAY_INFO: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            DisplayInfo info;
+            ui::StaticDisplayInfo info;
             const sp<IBinder> display = data.readStrongBinder();
-            const status_t result = getDisplayInfo(display, &info);
-            reply->writeInt32(result);
+            const status_t result = getStaticDisplayInfo(display, &info);
+            SAFE_PARCEL(reply->writeInt32, result);
             if (result != NO_ERROR) return result;
-            return reply->write(info);
+            SAFE_PARCEL(reply->write, info);
+            return NO_ERROR;
         }
-        case GET_DISPLAY_MODES: {
+        case GET_DYNAMIC_DISPLAY_INFO: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            Vector<ui::DisplayMode> modes;
+            ui::DynamicDisplayInfo info;
             const sp<IBinder> display = data.readStrongBinder();
-            const status_t result = getDisplayModes(display, &modes);
-            reply->writeInt32(result);
-            if (result == NO_ERROR) {
-                reply->writeUint32(static_cast<uint32_t>(modes.size()));
-                for (size_t i = 0; i < modes.size(); i++) {
-                    memcpy(reply->writeInplace(sizeof(ui::DisplayMode)), &modes[i],
-                           sizeof(ui::DisplayMode));
-                }
-            }
+            const status_t result = getDynamicDisplayInfo(display, &info);
+            SAFE_PARCEL(reply->writeInt32, result);
+            if (result != NO_ERROR) return result;
+            SAFE_PARCEL(reply->write, info);
             return NO_ERROR;
         }
         case GET_DISPLAY_STATS: {
@@ -1472,32 +1384,6 @@
             }
             return NO_ERROR;
         }
-        case GET_ACTIVE_DISPLAY_MODE: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> display = data.readStrongBinder();
-            int id = getActiveDisplayModeId(display);
-            reply->writeInt32(id);
-            return NO_ERROR;
-        }
-        case GET_DISPLAY_COLOR_MODES: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            Vector<ColorMode> colorModes;
-            sp<IBinder> display = nullptr;
-            status_t result = data.readStrongBinder(&display);
-            if (result != NO_ERROR) {
-                ALOGE("getDisplayColorModes failed to readStrongBinder: %d", result);
-                return result;
-            }
-            result = getDisplayColorModes(display, &colorModes);
-            reply->writeInt32(result);
-            if (result == NO_ERROR) {
-                reply->writeUint32(static_cast<uint32_t>(colorModes.size()));
-                for (size_t i = 0; i < colorModes.size(); ++i) {
-                    reply->writeInt32(static_cast<int32_t>(colorModes[i]));
-                }
-            }
-            return NO_ERROR;
-        }
         case GET_DISPLAY_NATIVE_PRIMARIES: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             ui::DisplayPrimaries primaries;
@@ -1518,18 +1404,6 @@
 
             return NO_ERROR;
         }
-        case GET_ACTIVE_COLOR_MODE: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> display = nullptr;
-            status_t result = data.readStrongBinder(&display);
-            if (result != NO_ERROR) {
-                ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
-                return result;
-            }
-            ColorMode colorMode = getActiveColorMode(display);
-            result = reply->writeInt32(static_cast<int32_t>(colorMode));
-            return result;
-        }
         case SET_ACTIVE_COLOR_MODE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = nullptr;
@@ -1639,23 +1513,6 @@
             setPowerMode(display, mode);
             return NO_ERROR;
         }
-        case GET_HDR_CAPABILITIES: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> display = nullptr;
-            status_t result = data.readStrongBinder(&display);
-            if (result != NO_ERROR) {
-                ALOGE("getHdrCapabilities failed to readStrongBinder: %d",
-                        result);
-                return result;
-            }
-            HdrCapabilities capabilities;
-            result = getHdrCapabilities(display, &capabilities);
-            reply->writeInt32(result);
-            if (result == NO_ERROR) {
-                reply->write(capabilities);
-            }
-            return NO_ERROR;
-        }
         case ENABLE_VSYNC_INJECTIONS: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             bool enable = false;
@@ -1862,7 +1719,7 @@
         case SET_DESIRED_DISPLAY_MODE_SPECS: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> displayToken = data.readStrongBinder();
-            int32_t defaultMode;
+            ui::DisplayModeId defaultMode;
             status_t result = data.readInt32(&defaultMode);
             if (result != NO_ERROR) {
                 ALOGE("setDesiredDisplayModeSpecs: failed to read defaultMode: %d", result);
@@ -1906,10 +1763,9 @@
                       result);
                 return result;
             }
-            result = setDesiredDisplayModeSpecs(displayToken, static_cast<size_t>(defaultMode),
-                                                allowGroupSwitching, primaryRefreshRateMin,
-                                                primaryRefreshRateMax, appRequestRefreshRateMin,
-                                                appRequestRefreshRateMax);
+            result = setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching,
+                                                primaryRefreshRateMin, primaryRefreshRateMax,
+                                                appRequestRefreshRateMin, appRequestRefreshRateMax);
             if (result != NO_ERROR) {
                 ALOGE("setDesiredDisplayModeSpecs: failed to call setDesiredDisplayModeSpecs: "
                       "%d",
@@ -1922,7 +1778,7 @@
         case GET_DESIRED_DISPLAY_MODE_SPECS: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> displayToken = data.readStrongBinder();
-            size_t defaultMode;
+            ui::DisplayModeId defaultMode;
             bool allowGroupSwitching;
             float primaryRefreshRateMin;
             float primaryRefreshRateMax;
@@ -1941,7 +1797,7 @@
                 return result;
             }
 
-            result = reply->writeInt32(static_cast<int32_t>(defaultMode));
+            result = reply->writeInt32(defaultMode);
             if (result != NO_ERROR) {
                 ALOGE("getDesiredDisplayModeSpecs: failed to write defaultMode: %d", result);
                 return result;
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 07fc069..6de3e97 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -34,9 +34,9 @@
 #include <utils/NativeHandle.h>
 
 #include <ui/DisplayStatInfo.h>
+#include <ui/DynamicDisplayInfo.h>
 #include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
 
 #include <gui/BufferItem.h>
@@ -48,7 +48,6 @@
 
 namespace android {
 
-using ui::ColorMode;
 using ui::Dataspace;
 
 namespace {
@@ -361,15 +360,12 @@
         return NAME_NOT_FOUND;
     }
 
-    HdrCapabilities hdrCapabilities;
-    status_t err =
-        composerService()->getHdrCapabilities(display, &hdrCapabilities);
-
-    if (err)
+    ui::DynamicDisplayInfo info;
+    if (status_t err = composerService()->getDynamicDisplayInfo(display, &info); err != NO_ERROR) {
         return err;
+    }
 
-    *supported = !hdrCapabilities.getSupportedHdrTypes().empty();
-
+    *supported = !info.hdrCapabilities.getSupportedHdrTypes().empty();
     return NO_ERROR;
 }
 
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 27fb2a8..0bd2c88 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -40,6 +40,7 @@
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <ui/DisplayMode.h>
+#include <ui/DynamicDisplayInfo.h>
 
 #ifndef NO_INPUT
 #include <input/InputWindow.h>
@@ -1815,39 +1816,35 @@
     return ComposerService::getComposerService()->getDisplayState(display, state);
 }
 
-status_t SurfaceComposerClient::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
-    return ComposerService::getComposerService()->getDisplayInfo(display, info);
+status_t SurfaceComposerClient::getStaticDisplayInfo(const sp<IBinder>& display,
+                                                     ui::StaticDisplayInfo* info) {
+    return ComposerService::getComposerService()->getStaticDisplayInfo(display, info);
 }
 
-status_t SurfaceComposerClient::getDisplayModes(const sp<IBinder>& display,
-                                                Vector<ui::DisplayMode>* modes) {
-    return ComposerService::getComposerService()->getDisplayModes(display, modes);
+status_t SurfaceComposerClient::getDynamicDisplayInfo(const sp<IBinder>& display,
+                                                      ui::DynamicDisplayInfo* info) {
+    return ComposerService::getComposerService()->getDynamicDisplayInfo(display, info);
 }
 
 status_t SurfaceComposerClient::getActiveDisplayMode(const sp<IBinder>& display,
                                                      ui::DisplayMode* mode) {
-    Vector<ui::DisplayMode> modes;
-    status_t result = getDisplayModes(display, &modes);
+    ui::DynamicDisplayInfo info;
+    status_t result = getDynamicDisplayInfo(display, &info);
     if (result != NO_ERROR) {
         return result;
     }
 
-    int activeId = getActiveDisplayModeId(display);
-    if (activeId < 0) {
-        ALOGE("No active mode found");
-        return NAME_NOT_FOUND;
+    if (const auto activeMode = info.getActiveDisplayMode()) {
+        *mode = *activeMode;
+        return NO_ERROR;
     }
 
-    *mode = modes[static_cast<size_t>(activeId)];
-    return NO_ERROR;
-}
-
-int SurfaceComposerClient::getActiveDisplayModeId(const sp<IBinder>& display) {
-    return ComposerService::getComposerService()->getActiveDisplayModeId(display);
+    ALOGE("Active display mode not found.");
+    return NAME_NOT_FOUND;
 }
 
 status_t SurfaceComposerClient::setDesiredDisplayModeSpecs(
-        const sp<IBinder>& displayToken, size_t defaultMode, bool allowGroupSwitching,
+        const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching,
         float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin,
         float appRequestRefreshRateMax) {
     return ComposerService::getComposerService()
@@ -1856,30 +1853,24 @@
                                          appRequestRefreshRateMin, appRequestRefreshRateMax);
 }
 
-status_t SurfaceComposerClient::getDesiredDisplayModeSpecs(
-        const sp<IBinder>& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching,
-        float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax,
-        float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) {
+status_t SurfaceComposerClient::getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                                           ui::DisplayModeId* outDefaultMode,
+                                                           bool* outAllowGroupSwitching,
+                                                           float* outPrimaryRefreshRateMin,
+                                                           float* outPrimaryRefreshRateMax,
+                                                           float* outAppRequestRefreshRateMin,
+                                                           float* outAppRequestRefreshRateMax) {
     return ComposerService::getComposerService()
             ->getDesiredDisplayModeSpecs(displayToken, outDefaultMode, outAllowGroupSwitching,
                                          outPrimaryRefreshRateMin, outPrimaryRefreshRateMax,
                                          outAppRequestRefreshRateMin, outAppRequestRefreshRateMax);
 }
 
-status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
-        Vector<ColorMode>* outColorModes) {
-    return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
-}
-
 status_t SurfaceComposerClient::getDisplayNativePrimaries(const sp<IBinder>& display,
         ui::DisplayPrimaries& outPrimaries) {
     return ComposerService::getComposerService()->getDisplayNativePrimaries(display, outPrimaries);
 }
 
-ColorMode SurfaceComposerClient::getActiveColorMode(const sp<IBinder>& display) {
-    return ComposerService::getComposerService()->getActiveColorMode(display);
-}
-
 status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display,
         ColorMode colorMode) {
     return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
@@ -1932,12 +1923,6 @@
     return ComposerService::getComposerService()->getAnimationFrameStats(outStats);
 }
 
-status_t SurfaceComposerClient::getHdrCapabilities(const sp<IBinder>& display,
-        HdrCapabilities* outCapabilities) {
-    return ComposerService::getComposerService()->getHdrCapabilities(display,
-            outCapabilities);
-}
-
 status_t SurfaceComposerClient::getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
                                                                       ui::PixelFormat* outFormat,
                                                                       ui::Dataspace* outDataspace,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index e842382..1dcfe2e 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -30,9 +30,9 @@
 
 #include <binder/IPCThreadState.h>
 
-#include <ui/DisplayInfo.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
+#include <ui/StaticDisplayInfo.h>
 
 #include <gui/BufferQueueCore.h>
 #include <gui/ISurfaceComposer.h>
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 292838e..d0ab480 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -33,6 +33,7 @@
 
 #include <ui/ConfigStoreTypes.h>
 #include <ui/DisplayId.h>
+#include <ui/DisplayMode.h>
 #include <ui/DisplayedFrameStats.h>
 #include <ui/FrameStats.h>
 #include <ui/GraphicBuffer.h>
@@ -54,7 +55,6 @@
 struct client_cache_t;
 struct ComposerState;
 struct DisplayCaptureArgs;
-struct DisplayInfo;
 struct DisplayStatInfo;
 struct DisplayState;
 struct InputWindowCommands;
@@ -74,6 +74,8 @@
 
 struct DisplayMode;
 struct DisplayState;
+struct DynamicDisplayInfo;
+struct StaticDisplayInfo;
 
 } // namespace ui
 
@@ -202,26 +204,17 @@
     virtual status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState*) = 0;
 
     /**
-     * Get immutable information about given physical display.
+     * Gets immutable information about given physical display.
      */
-    virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo*) = 0;
+    virtual status_t getStaticDisplayInfo(const sp<IBinder>& display, ui::StaticDisplayInfo*) = 0;
 
     /**
-     * Get modes supported by given physical display.
+     * Gets dynamic information about given physical display.
      */
-    virtual status_t getDisplayModes(const sp<IBinder>& display, Vector<ui::DisplayMode>*) = 0;
+    virtual status_t getDynamicDisplayInfo(const sp<IBinder>& display, ui::DynamicDisplayInfo*) = 0;
 
-    /**
-     * Get the index into modes returned by getDisplayModes,
-     * corresponding to the active mode.
-     */
-    virtual int getActiveDisplayModeId(const sp<IBinder>& display) = 0;
-
-    virtual status_t getDisplayColorModes(const sp<IBinder>& display,
-            Vector<ui::ColorMode>* outColorModes) = 0;
     virtual status_t getDisplayNativePrimaries(const sp<IBinder>& display,
             ui::DisplayPrimaries& primaries) = 0;
-    virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& display) = 0;
     virtual status_t setActiveColorMode(const sp<IBinder>& display,
             ui::ColorMode colorMode) = 0;
 
@@ -296,13 +289,6 @@
      */
     virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0;
 
-    /* Gets the supported HDR capabilities of the given display.
-     *
-     * Requires the ACCESS_SURFACE_FLINGER permission.
-     */
-    virtual status_t getHdrCapabilities(const sp<IBinder>& display,
-            HdrCapabilities* outCapabilities) const = 0;
-
     virtual status_t enableVSyncInjections(bool enable) = 0;
 
     virtual status_t injectVSync(nsecs_t when) = 0;
@@ -397,20 +383,21 @@
      *
      * defaultMode is used to narrow the list of display modes SurfaceFlinger will consider
      * switching between. Only modes with a mode group and resolution matching defaultMode
-     * will be considered for switching. The defaultMode index corresponds to the list of modes
-     * returned from getDisplayModes().
+     * will be considered for switching. The defaultMode corresponds to an ID of mode in the list
+     * of supported modes returned from getDynamicDisplayInfo().
      */
-    virtual status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t defaultMode,
-                                                bool allowGroupSwitching,
-                                                float primaryRefreshRateMin,
-                                                float primaryRefreshRateMax,
-                                                float appRequestRefreshRateMin,
-                                                float appRequestRefreshRateMax) = 0;
+    virtual status_t setDesiredDisplayModeSpecs(
+            const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode,
+            bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax,
+            float appRequestRefreshRateMin, float appRequestRefreshRateMax) = 0;
 
-    virtual status_t getDesiredDisplayModeSpecs(
-            const sp<IBinder>& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching,
-            float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax,
-            float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) = 0;
+    virtual status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                                ui::DisplayModeId* outDefaultMode,
+                                                bool* outAllowGroupSwitching,
+                                                float* outPrimaryRefreshRateMin,
+                                                float* outPrimaryRefreshRateMax,
+                                                float* outAppRequestRefreshRateMin,
+                                                float* outAppRequestRefreshRateMax) = 0;
     /*
      * Gets whether brightness operations are supported on a display.
      *
@@ -534,7 +521,7 @@
         // Java by ActivityManagerService.
         BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
         CREATE_CONNECTION,
-        GET_DISPLAY_INFO,
+        GET_STATIC_DISPLAY_INFO,
         CREATE_DISPLAY_EVENT_CONNECTION,
         CREATE_DISPLAY,
         DESTROY_DISPLAY,
@@ -542,8 +529,8 @@
         SET_TRANSACTION_STATE,
         AUTHENTICATE_SURFACE,
         GET_SUPPORTED_FRAME_TIMESTAMPS,
-        GET_DISPLAY_MODES,
-        GET_ACTIVE_DISPLAY_MODE,
+        GET_DISPLAY_MODES,       // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+        GET_ACTIVE_DISPLAY_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
         GET_DISPLAY_STATE,
         CAPTURE_DISPLAY,
         CAPTURE_LAYERS,
@@ -551,9 +538,9 @@
         GET_ANIMATION_FRAME_STATS,
         SET_POWER_MODE,
         GET_DISPLAY_STATS,
-        GET_HDR_CAPABILITIES,
-        GET_DISPLAY_COLOR_MODES,
-        GET_ACTIVE_COLOR_MODE,
+        GET_HDR_CAPABILITIES,    // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+        GET_DISPLAY_COLOR_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+        GET_ACTIVE_COLOR_MODE,   // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
         SET_ACTIVE_COLOR_MODE,
         ENABLE_VSYNC_INJECTIONS,
         INJECT_VSYNC,
@@ -586,6 +573,7 @@
         ADD_TRANSACTION_TRACE_LISTENER,
         GET_GPU_CONTEXT_PRIORITY,
         GET_EXTRA_BUFFER_COUNT,
+        GET_DYNAMIC_DISPLAY_INFO,
         // Always append new enum to the end.
     };
 
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index e89f3a7..2b72b73 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -108,43 +108,33 @@
     static status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState*);
 
     // Get immutable information about given physical display.
-    static status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo*);
+    static status_t getStaticDisplayInfo(const sp<IBinder>& display, ui::StaticDisplayInfo*);
 
-    // Get modes supported by given physical display.
-    static status_t getDisplayModes(const sp<IBinder>& display, Vector<ui::DisplayMode>*);
+    // Get dynamic information about given physical display.
+    static status_t getDynamicDisplayInfo(const sp<IBinder>& display, ui::DynamicDisplayInfo*);
 
-    // Get the ID of the active DisplayMode, as getDisplayModes index.
-    static int getActiveDisplayModeId(const sp<IBinder>& display);
-
-    // Shorthand for getDisplayModes element at getActiveDisplayModeId index.
+    // Shorthand for the active display mode from getDynamicDisplayInfo().
+    // TODO(b/180391891): Update clients to use getDynamicDisplayInfo and remove this function.
     static status_t getActiveDisplayMode(const sp<IBinder>& display, ui::DisplayMode*);
 
     // Sets the refresh rate boundaries for the display.
-    static status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t defaultMode,
-                                               bool allowGroupSwitching,
-                                               float primaryRefreshRateMin,
-                                               float primaryRefreshRateMax,
-                                               float appRequestRefreshRateMin,
-                                               float appRequestRefreshRateMax);
+    static status_t setDesiredDisplayModeSpecs(
+            const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode,
+            bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax,
+            float appRequestRefreshRateMin, float appRequestRefreshRateMax);
     // Gets the refresh rate boundaries for the display.
     static status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
-                                               size_t* outDefaultMode, bool* outAllowGroupSwitching,
+                                               ui::DisplayModeId* outDefaultMode,
+                                               bool* outAllowGroupSwitching,
                                                float* outPrimaryRefreshRateMin,
                                                float* outPrimaryRefreshRateMax,
                                                float* outAppRequestRefreshRateMin,
                                                float* outAppRequestRefreshRateMax);
 
-    // Gets the list of supported color modes for the given display
-    static status_t getDisplayColorModes(const sp<IBinder>& display,
-            Vector<ui::ColorMode>* outColorModes);
-
     // Get the coordinates of the display's native color primaries
     static status_t getDisplayNativePrimaries(const sp<IBinder>& display,
             ui::DisplayPrimaries& outPrimaries);
 
-    // Gets the active color mode for the given display
-    static ui::ColorMode getActiveColorMode(const sp<IBinder>& display);
-
     // Sets the active color mode for the given display
     static status_t setActiveColorMode(const sp<IBinder>& display,
             ui::ColorMode colorMode);
@@ -583,9 +573,6 @@
     static status_t clearAnimationFrameStats();
     static status_t getAnimationFrameStats(FrameStats* outStats);
 
-    static status_t getHdrCapabilities(const sp<IBinder>& display,
-            HdrCapabilities* outCapabilities);
-
     static void setDisplayProjection(const sp<IBinder>& token, ui::Rotation orientation,
                                      const Rect& layerStackRect, const Rect& displayRect);
 
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 43909ac..3397198 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -32,6 +32,7 @@
 #include <inttypes.h>
 #include <private/gui/ComposerService.h>
 #include <ui/BufferQueueDefs.h>
+#include <ui/DisplayMode.h>
 #include <ui/Rect.h>
 #include <utils/String8.h>
 
@@ -734,10 +735,11 @@
     }
 
     void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {}
-    status_t getDisplayInfo(const sp<IBinder>& /*display*/, DisplayInfo*) override {
+    status_t getStaticDisplayInfo(const sp<IBinder>& /*display*/, ui::StaticDisplayInfo*) override {
         return NO_ERROR;
     }
-    status_t getDisplayModes(const sp<IBinder>& /*display*/, Vector<ui::DisplayMode>*) override {
+    status_t getDynamicDisplayInfo(const sp<IBinder>& /*display*/,
+                                   ui::DynamicDisplayInfo*) override {
         return NO_ERROR;
     }
     status_t getDisplayState(const sp<IBinder>& /*display*/, ui::DisplayState*) override {
@@ -745,19 +747,10 @@
     }
     status_t getDisplayStats(const sp<IBinder>& /*display*/,
             DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
-    int getActiveDisplayModeId(const sp<IBinder>& /*display*/) override { return 0; }
-    status_t getDisplayColorModes(const sp<IBinder>& /*display*/,
-            Vector<ColorMode>* /*outColorModes*/) override {
-        return NO_ERROR;
-    }
     status_t getDisplayNativePrimaries(const sp<IBinder>& /*display*/,
             ui::DisplayPrimaries& /*primaries*/) override {
         return NO_ERROR;
     }
-    ColorMode getActiveColorMode(const sp<IBinder>& /*display*/)
-            override {
-        return ColorMode::NATIVE;
-    }
     status_t setActiveColorMode(const sp<IBinder>& /*display*/,
         ColorMode /*colorMode*/) override { return NO_ERROR; }
     status_t captureDisplay(const DisplayCaptureArgs& /* captureArgs */,
@@ -787,10 +780,6 @@
     status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
         return NO_ERROR;
     }
-    status_t getHdrCapabilities(const sp<IBinder>& /*display*/,
-            HdrCapabilities* /*outCapabilities*/) const override {
-        return NO_ERROR;
-    }
     status_t enableVSyncInjections(bool /*enable*/) override {
         return NO_ERROR;
     }
@@ -843,7 +832,8 @@
             const sp<IRegionSamplingListener>& /*listener*/) override {
         return NO_ERROR;
     }
-    status_t setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/, size_t /*defaultMode*/,
+    status_t setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
+                                        ui::DisplayModeId /*defaultMode*/,
                                         bool /*allowGroupSwitching*/,
                                         float /*primaryRefreshRateMin*/,
                                         float /*primaryRefreshRateMax*/,
@@ -852,7 +842,7 @@
         return NO_ERROR;
     }
     status_t getDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
-                                        size_t* /*outDefaultMode*/,
+                                        ui::DisplayModeId* /*outDefaultMode*/,
                                         bool* /*outAllowGroupSwitching*/,
                                         float* /*outPrimaryRefreshRateMin*/,
                                         float* /*outPrimaryRefreshRateMax*/,
diff --git a/libs/nativedisplay/ADisplay.cpp b/libs/nativedisplay/ADisplay.cpp
index c595aa6..6288194 100644
--- a/libs/nativedisplay/ADisplay.cpp
+++ b/libs/nativedisplay/ADisplay.cpp
@@ -16,10 +16,11 @@
 
 #include <apex/display.h>
 #include <gui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
 #include <ui/DisplayMode.h>
+#include <ui/DynamicDisplayInfo.h>
 #include <ui/GraphicTypes.h>
 #include <ui/PixelFormat.h>
+#include <ui/StaticDisplayInfo.h>
 
 #include <algorithm>
 #include <optional>
@@ -33,6 +34,11 @@
  */
 struct DisplayConfigImpl {
     /**
+     * The ID of the display configuration.
+     */
+    size_t id;
+
+    /**
      * The width in pixels of the display configuration.
      */
     int32_t width{0};
@@ -139,17 +145,19 @@
     for (int i = 0; i < size; ++i) {
         const sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]);
 
-        DisplayInfo info;
-        if (const status_t status = SurfaceComposerClient::getDisplayInfo(token, &info);
+        ui::StaticDisplayInfo staticInfo;
+        if (const status_t status = SurfaceComposerClient::getStaticDisplayInfo(token, &staticInfo);
             status != OK) {
             return status;
         }
 
-        Vector<ui::DisplayMode> modes;
-        if (const status_t status = SurfaceComposerClient::getDisplayModes(token, &modes);
+        ui::DynamicDisplayInfo dynamicInfo;
+        if (const status_t status =
+                    SurfaceComposerClient::getDynamicDisplayInfo(token, &dynamicInfo);
             status != OK) {
             return status;
         }
+        const auto& modes = dynamicInfo.supportedDisplayModes;
         if (modes.empty()) {
             return NO_INIT;
         }
@@ -159,9 +167,9 @@
         for (int j = 0; j < modes.size(); ++j) {
             const ui::DisplayMode& mode = modes[j];
             modesPerDisplay[i].emplace_back(
-                    DisplayConfigImpl{mode.resolution.getWidth(), mode.resolution.getHeight(),
-                                      info.density, mode.refreshRate, mode.sfVsyncOffset,
-                                      mode.appVsyncOffset});
+                    DisplayConfigImpl{static_cast<size_t>(mode.id), mode.resolution.getWidth(),
+                                      mode.resolution.getHeight(), staticInfo.density,
+                                      mode.refreshRate, mode.sfVsyncOffset, mode.appVsyncOffset});
         }
     }
 
@@ -257,15 +265,22 @@
     CHECK_NOT_NULL(display);
 
     sp<IBinder> token = getToken(display);
-    const int index = SurfaceComposerClient::getActiveDisplayModeId(token);
-    if (index < 0) {
-        return index;
+    ui::DynamicDisplayInfo info;
+    if (const auto status = SurfaceComposerClient::getDynamicDisplayInfo(token, &info);
+        status != OK) {
+        return status;
     }
 
     DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display);
+    for (size_t i = 0; i < impl->numConfigs; i++) {
+        auto* config = impl->configs + i;
+        if (config->id == info.activeDisplayModeId) {
+            *outConfig = reinterpret_cast<ADisplayConfig*>(config);
+            return OK;
+        }
+    }
 
-    *outConfig = reinterpret_cast<ADisplayConfig*>(impl->configs + index);
-    return OK;
+    return NAME_NOT_FOUND;
 }
 
 float ADisplayConfig_getDensity(ADisplayConfig* config) {
diff --git a/libs/nativedisplay/include/apex/display.h b/libs/nativedisplay/include/apex/display.h
index a7eaf87..bd94b55 100644
--- a/libs/nativedisplay/include/apex/display.h
+++ b/libs/nativedisplay/include/apex/display.h
@@ -97,6 +97,11 @@
  * such an update is observed, then this method should be recalled to get the
  * new current configuration.
  *
+ * After a subsequent hotplug "connected" event the supported display configs
+ * may change. Then the preloaded display configs will be stale and the
+ * call for current config may return NAME_NOT_FOUND. In this case the client
+ * should release and re-acquire the display handle.
+ *
  * Returns OK on success, -errno on failure.
  */
 int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig);
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 714ee3e..f160c29 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -105,7 +105,8 @@
     srcs: [
         "DebugUtils.cpp",
         "DeviceProductInfo.cpp",
-        "DisplayInfo.cpp",
+        "DisplayMode.cpp",
+        "DynamicDisplayInfo.cpp",
         "Fence.cpp",
         "FenceTime.cpp",
         "FrameStats.cpp",
@@ -120,6 +121,7 @@
         "PixelFormat.cpp",
         "PublicFormat.cpp",
         "Size.cpp",
+        "StaticDisplayInfo.cpp",
     ],
 
     include_dirs: [
diff --git a/libs/ui/DisplayMode.cpp b/libs/ui/DisplayMode.cpp
new file mode 100644
index 0000000..cf05dbf
--- /dev/null
+++ b/libs/ui/DisplayMode.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2021 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 <ui/DisplayMode.h>
+
+#include <cstdint>
+
+#include <ui/FlattenableHelpers.h>
+
+#define RETURN_IF_ERROR(op) \
+    if (const status_t status = (op); status != OK) return status;
+
+namespace android::ui {
+
+size_t DisplayMode::getFlattenedSize() const {
+    return FlattenableHelpers::getFlattenedSize(id) +
+            FlattenableHelpers::getFlattenedSize(resolution) +
+            FlattenableHelpers::getFlattenedSize(xDpi) +
+            FlattenableHelpers::getFlattenedSize(yDpi) +
+            FlattenableHelpers::getFlattenedSize(refreshRate) +
+            FlattenableHelpers::getFlattenedSize(appVsyncOffset) +
+            FlattenableHelpers::getFlattenedSize(sfVsyncOffset) +
+            FlattenableHelpers::getFlattenedSize(presentationDeadline) +
+            FlattenableHelpers::getFlattenedSize(group);
+}
+
+status_t DisplayMode::flatten(void* buffer, size_t size) const {
+    if (size < getFlattenedSize()) {
+        return NO_MEMORY;
+    }
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, id));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, resolution));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, xDpi));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, yDpi));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, refreshRate));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, appVsyncOffset));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, sfVsyncOffset));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, presentationDeadline));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, group));
+    return OK;
+}
+
+status_t DisplayMode::unflatten(const void* buffer, size_t size) {
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &id));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &resolution));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &xDpi));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &yDpi));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &refreshRate));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &appVsyncOffset));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &sfVsyncOffset));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &presentationDeadline));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &group));
+    return OK;
+}
+
+} // namespace android::ui
diff --git a/libs/ui/DynamicDisplayInfo.cpp b/libs/ui/DynamicDisplayInfo.cpp
new file mode 100644
index 0000000..11acdae
--- /dev/null
+++ b/libs/ui/DynamicDisplayInfo.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2021 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 <ui/DynamicDisplayInfo.h>
+
+#include <cstdint>
+
+#include <ui/FlattenableHelpers.h>
+
+#define RETURN_IF_ERROR(op) \
+    if (const status_t status = (op); status != OK) return status;
+
+namespace android::ui {
+
+std::optional<ui::DisplayMode> DynamicDisplayInfo::getActiveDisplayMode() const {
+    for (const auto& currMode : supportedDisplayModes) {
+        if (currMode.id == activeDisplayModeId) {
+            return currMode;
+        }
+    }
+    return {};
+}
+
+size_t DynamicDisplayInfo::getFlattenedSize() const {
+    return FlattenableHelpers::getFlattenedSize(supportedDisplayModes) +
+            FlattenableHelpers::getFlattenedSize(activeDisplayModeId) +
+            FlattenableHelpers::getFlattenedSize(supportedColorModes) +
+            FlattenableHelpers::getFlattenedSize(activeColorMode) +
+            FlattenableHelpers::getFlattenedSize(hdrCapabilities);
+}
+
+status_t DynamicDisplayInfo::flatten(void* buffer, size_t size) const {
+    if (size < getFlattenedSize()) {
+        return NO_MEMORY;
+    }
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedDisplayModes));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeDisplayModeId));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedColorModes));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeColorMode));
+    RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, hdrCapabilities));
+    return OK;
+}
+
+status_t DynamicDisplayInfo::unflatten(const void* buffer, size_t size) {
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedDisplayModes));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeDisplayModeId));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedColorModes));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeColorMode));
+    RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &hdrCapabilities));
+    return OK;
+}
+
+} // namespace android::ui
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
index a5b3e89..aec2fac 100644
--- a/libs/ui/HdrCapabilities.cpp
+++ b/libs/ui/HdrCapabilities.cpp
@@ -23,10 +23,6 @@
 #pragma clang diagnostic ignored "-Wundefined-reinterpret-cast"
 #endif
 
-HdrCapabilities::~HdrCapabilities() = default;
-HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) noexcept = default;
-HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) noexcept = default;
-
 size_t HdrCapabilities::getFlattenedSize() const {
     return  sizeof(mMaxLuminance) +
             sizeof(mMaxAverageLuminance) +
diff --git a/libs/ui/DisplayInfo.cpp b/libs/ui/StaticDisplayInfo.cpp
similarity index 86%
rename from libs/ui/DisplayInfo.cpp
rename to libs/ui/StaticDisplayInfo.cpp
index 73a78af..b66b281 100644
--- a/libs/ui/DisplayInfo.cpp
+++ b/libs/ui/StaticDisplayInfo.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <ui/DisplayInfo.h>
+#include <ui/StaticDisplayInfo.h>
 
 #include <cstdint>
 
@@ -23,16 +23,16 @@
 #define RETURN_IF_ERROR(op) \
     if (const status_t status = (op); status != OK) return status;
 
-namespace android {
+namespace android::ui {
 
-size_t DisplayInfo::getFlattenedSize() const {
+size_t StaticDisplayInfo::getFlattenedSize() const {
     return FlattenableHelpers::getFlattenedSize(connectionType) +
             FlattenableHelpers::getFlattenedSize(density) +
             FlattenableHelpers::getFlattenedSize(secure) +
             FlattenableHelpers::getFlattenedSize(deviceProductInfo);
 }
 
-status_t DisplayInfo::flatten(void* buffer, size_t size) const {
+status_t StaticDisplayInfo::flatten(void* buffer, size_t size) const {
     if (size < getFlattenedSize()) {
         return NO_MEMORY;
     }
@@ -43,7 +43,7 @@
     return OK;
 }
 
-status_t DisplayInfo::unflatten(void const* buffer, size_t size) {
+status_t StaticDisplayInfo::unflatten(void const* buffer, size_t size) {
     RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &connectionType));
     RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &density));
     RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &secure));
@@ -51,4 +51,4 @@
     return OK;
 }
 
-} // namespace android
+} // namespace android::ui
diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h
index 145d7ef..56f68e7 100644
--- a/libs/ui/include/ui/DisplayMode.h
+++ b/libs/ui/include/ui/DisplayMode.h
@@ -16,15 +16,21 @@
 
 #pragma once
 
+#include <cstdint>
 #include <type_traits>
 
 #include <ui/Size.h>
+#include <utils/Flattenable.h>
 #include <utils/Timers.h>
 
 namespace android::ui {
 
+// This value is going to be serialized over binder so we prefer a fixed width type.
+using DisplayModeId = int32_t;
+
 // Mode supported by physical display.
-struct DisplayMode {
+struct DisplayMode : LightFlattenable<DisplayMode> {
+    DisplayModeId id;
     ui::Size resolution;
     float xDpi = 0;
     float yDpi = 0;
@@ -33,9 +39,12 @@
     nsecs_t appVsyncOffset = 0;
     nsecs_t sfVsyncOffset = 0;
     nsecs_t presentationDeadline = 0;
-    int group = -1;
-};
+    int32_t group = -1;
 
-static_assert(std::is_trivially_copyable_v<DisplayMode>);
+    bool isFixedSize() const { return false; }
+    size_t getFlattenedSize() const;
+    status_t flatten(void* buffer, size_t size) const;
+    status_t unflatten(const void* buffer, size_t size);
+};
 
 } // namespace android::ui
diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h
new file mode 100644
index 0000000..6c349b7
--- /dev/null
+++ b/libs/ui/include/ui/DynamicDisplayInfo.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+#include "DisplayMode.h"
+
+#include <cstdint>
+#include <optional>
+#include <vector>
+
+#include <ui/GraphicTypes.h>
+#include <ui/HdrCapabilities.h>
+#include <utils/Flattenable.h>
+
+namespace android::ui {
+
+// Information about a physical display which may change on hotplug reconnect.
+struct DynamicDisplayInfo : LightFlattenable<DynamicDisplayInfo> {
+    std::vector<ui::DisplayMode> supportedDisplayModes;
+
+    // This struct is going to be serialized over binder, so
+    // we can't use size_t because it may have different width
+    // in the client process.
+    int32_t activeDisplayModeId;
+
+    std::vector<ui::ColorMode> supportedColorModes;
+    ui::ColorMode activeColorMode;
+    HdrCapabilities hdrCapabilities;
+
+    std::optional<ui::DisplayMode> getActiveDisplayMode() const;
+
+    bool isFixedSize() const { return false; }
+    size_t getFlattenedSize() const;
+    status_t flatten(void* buffer, size_t size) const;
+    status_t unflatten(const void* buffer, size_t size);
+};
+
+} // namespace android::ui
diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
index 65ac26c..813adde 100644
--- a/libs/ui/include/ui/HdrCapabilities.h
+++ b/libs/ui/include/ui/HdrCapabilities.h
@@ -36,18 +36,12 @@
         mMaxAverageLuminance(maxAverageLuminance),
         mMinLuminance(minLuminance) {}
 
-    // Make this move-constructable and move-assignable
-    HdrCapabilities(HdrCapabilities&& other) noexcept;
-    HdrCapabilities& operator=(HdrCapabilities&& other) noexcept;
-
     HdrCapabilities()
       : mSupportedHdrTypes(),
         mMaxLuminance(-1.0f),
         mMaxAverageLuminance(-1.0f),
         mMinLuminance(-1.0f) {}
 
-    ~HdrCapabilities();
-
     const std::vector<ui::Hdr>& getSupportedHdrTypes() const {
         return mSupportedHdrTypes;
     }
diff --git a/libs/ui/include/ui/DisplayInfo.h b/libs/ui/include/ui/StaticDisplayInfo.h
similarity index 90%
rename from libs/ui/include/ui/DisplayInfo.h
rename to libs/ui/include/ui/StaticDisplayInfo.h
index 03e0a38..e86ca29 100644
--- a/libs/ui/include/ui/DisplayInfo.h
+++ b/libs/ui/include/ui/StaticDisplayInfo.h
@@ -17,17 +17,16 @@
 #pragma once
 
 #include <optional>
-#include <type_traits>
 
 #include <ui/DeviceProductInfo.h>
 #include <utils/Flattenable.h>
 
-namespace android {
+namespace android::ui {
 
 enum class DisplayConnectionType { Internal, External };
 
 // Immutable information about physical display.
-struct DisplayInfo : LightFlattenable<DisplayInfo> {
+struct StaticDisplayInfo : LightFlattenable<StaticDisplayInfo> {
     DisplayConnectionType connectionType = DisplayConnectionType::Internal;
     float density = 0.f;
     bool secure = false;
@@ -39,4 +38,4 @@
     status_t unflatten(void const* buffer, size_t size);
 };
 
-} // namespace android
+} // namespace android::ui
diff --git a/libs/ui/include_vndk/ui/DisplayInfo.h b/libs/ui/include_vndk/ui/DisplayInfo.h
deleted file mode 120000
index 75f14cf..0000000
--- a/libs/ui/include_vndk/ui/DisplayInfo.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/ui/DisplayInfo.h
\ No newline at end of file
diff --git a/libs/ui/include_vndk/ui/StaticDisplayInfo.h b/libs/ui/include_vndk/ui/StaticDisplayInfo.h
new file mode 120000
index 0000000..541a7a3
--- /dev/null
+++ b/libs/ui/include_vndk/ui/StaticDisplayInfo.h
@@ -0,0 +1 @@
+../../include/ui/StaticDisplayInfo.h
\ No newline at end of file
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
index 95ba9f0..633668e 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
@@ -21,9 +21,9 @@
 #include <string>
 
 #include <ui/DisplayId.h>
-#include <ui/DisplayInfo.h>
 #include <ui/PixelFormat.h>
 #include <ui/Size.h>
+#include <ui/StaticDisplayInfo.h>
 
 #include "DisplayHardware/DisplayIdentification.h"
 #include "DisplayHardware/PowerAdvisor.h"
@@ -39,7 +39,7 @@
 struct DisplayCreationArgs {
     struct Physical {
         DisplayId id;
-        DisplayConnectionType type;
+        ui::DisplayConnectionType type;
     };
 
     // Required for physical displays. Gives the HWC display id for the existing
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 0b0b8d5..a605fe1 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -55,7 +55,8 @@
     editState().isSecure = args.isSecure;
     editState().displaySpace.bounds = Rect(args.pixels);
     setLayerStackFilter(args.layerStackId,
-                        args.physical && args.physical->type == DisplayConnectionType::Internal);
+                        args.physical &&
+                                args.physical->type == ui::DisplayConnectionType::Internal);
     setName(args.name);
     mGpuVirtualDisplayIdGenerator = args.gpuVirtualDisplayIdGenerator;
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 348ec39..8a83639 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -35,8 +35,8 @@
 #include <compositionengine/mock/RenderSurface.h>
 #include <gtest/gtest.h>
 #include <renderengine/mock/RenderEngine.h>
-#include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
+#include <ui/StaticDisplayInfo.h>
 
 #include "MockHWC2.h"
 #include "MockHWComposer.h"
@@ -169,7 +169,7 @@
 
     DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() {
         return DisplayCreationArgsBuilder()
-                .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal})
+                .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal})
                 .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
                 .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888))
                 .setIsSecure(true)
@@ -265,7 +265,7 @@
     mDisplay->setConfiguration(
             DisplayCreationArgsBuilder()
                     .setUseHwcVirtualDisplays(true)
-                    .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal})
+                    .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal})
                     .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH))
                     .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888))
                     .setIsSecure(true)
@@ -286,7 +286,7 @@
     mDisplay->setConfiguration(
             DisplayCreationArgsBuilder()
                     .setUseHwcVirtualDisplays(true)
-                    .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::External})
+                    .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::External})
                     .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH))
                     .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888))
                     .setIsSecure(false)
@@ -1018,7 +1018,7 @@
     std::shared_ptr<Display> mDisplay = impl::createDisplayTemplated<
             Display>(mCompositionEngine,
                      DisplayCreationArgsBuilder()
-                             .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal})
+                             .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal})
                              .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
                              .setPixelFormat(static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888))
                              .setIsSecure(true)
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index ab00385..bac894a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -91,7 +91,7 @@
     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(getDisplayConnectionType, ui::DisplayConnectionType(PhysicalDisplayId));
     MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(PhysicalDisplayId));
     MOCK_CONST_METHOD2(getDisplayVsyncPeriod, status_t(PhysicalDisplayId, nsecs_t*));
     MOCK_METHOD4(setActiveModeWithConstraints,
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index c751f22..36c4c4d 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -173,7 +173,7 @@
 
 DisplayModePtr DisplayDevice::getMode(DisplayModeId modeId) const {
     const auto id = modeId.value();
-    if (id < mSupportedModes.size()) {
+    if (static_cast<size_t>(id) < mSupportedModes.size()) {
         return mSupportedModes[id];
     }
     return nullptr;
@@ -254,7 +254,7 @@
 std::string DisplayDevice::getDebugName() const {
     const char* type = "virtual";
     if (mConnectionType) {
-        type = *mConnectionType == DisplayConnectionType::Internal ? "internal" : "external";
+        type = *mConnectionType == ui::DisplayConnectionType::Internal ? "internal" : "external";
     }
 
     return base::StringPrintf("DisplayDevice{%s, %s%s, \"%s\"}", to_string(getId()).c_str(), type,
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index b4db933..a94bfa2 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -28,11 +28,11 @@
 #include <renderengine/RenderEngine.h>
 #include <system/window.h>
 #include <ui/DisplayId.h>
-#include <ui/DisplayInfo.h>
 #include <ui/DisplayState.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
+#include <ui/StaticDisplayInfo.h>
 #include <ui/Transform.h>
 #include <utils/Errors.h>
 #include <utils/Mutex.h>
@@ -74,7 +74,7 @@
         return mCompositionDisplay;
     }
 
-    std::optional<DisplayConnectionType> getConnectionType() const { return mConnectionType; }
+    std::optional<ui::DisplayConnectionType> getConnectionType() const { return mConnectionType; }
 
     bool isVirtual() const { return !mConnectionType; }
     bool isPrimary() const { return mIsPrimary; }
@@ -195,7 +195,7 @@
     HWComposer& mHwComposer;
     const wp<IBinder> mDisplayToken;
     const int32_t mSequenceId;
-    const std::optional<DisplayConnectionType> mConnectionType;
+    const std::optional<ui::DisplayConnectionType> mConnectionType;
 
     const std::shared_ptr<compositionengine::Display> mCompositionDisplay;
 
@@ -222,7 +222,7 @@
 struct DisplayDeviceState {
     struct Physical {
         PhysicalDisplayId id;
-        DisplayConnectionType type;
+        ui::DisplayConnectionType type;
         hardware::graphics::composer::hal::HWDisplayId hwcDisplayId;
         std::optional<DeviceProductInfo> deviceProductInfo;
         DisplayModes supportedModes;
@@ -263,7 +263,7 @@
     const std::shared_ptr<compositionengine::Display> compositionDisplay;
 
     int32_t sequenceId{0};
-    std::optional<DisplayConnectionType> connectionType;
+    std::optional<ui::DisplayConnectionType> connectionType;
     bool isSecure{false};
     sp<ANativeWindow> nativeWindow;
     sp<compositionengine::DisplaySurface> displaySurface;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 1f0f3c3..853c05b 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/DisplayMode.h>
 #include <ui/Size.h>
 #include <utils/Timers.h>
 
@@ -36,7 +37,7 @@
 class DisplayMode;
 using DisplayModePtr = std::shared_ptr<const DisplayMode>;
 using DisplayModes = std::vector<DisplayModePtr>;
-using DisplayModeId = StrongTyping<size_t, struct DisplayModeIdTag, Compare, Hash>;
+using DisplayModeId = StrongTyping<ui::DisplayModeId, struct DisplayModeIdTag, Compare, Hash>;
 
 class DisplayMode {
 public:
@@ -139,7 +140,7 @@
 };
 
 inline std::string to_string(const DisplayMode& mode) {
-    return base::StringPrintf("{id=%zu, hwcId=%d, width=%d, height=%d, refreshRate=%s, "
+    return base::StringPrintf("{id=%d, hwcId=%d, width=%d, height=%d, refreshRate=%s, "
                               "dpiX=%.2f, dpiY=%.2f, group=%d}",
                               mode.getId().value(), mode.getHwcId(), mode.getWidth(),
                               mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpiX(),
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 71a3276..d04b5f7 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -264,7 +264,7 @@
     return Error::NONE;
 }
 
-Error Display::getConnectionType(android::DisplayConnectionType* outType) const {
+Error Display::getConnectionType(ui::DisplayConnectionType* outType) const {
     if (mType != DisplayType::PHYSICAL) return Error::BAD_DISPLAY;
 
     using ConnectionType = Hwc2::IComposerClient::DisplayConnectionType;
@@ -274,9 +274,8 @@
         return error;
     }
 
-    *outType = connectionType == ConnectionType::INTERNAL
-            ? android::DisplayConnectionType::Internal
-            : android::DisplayConnectionType::External;
+    *outType = connectionType == ConnectionType::INTERNAL ? ui::DisplayConnectionType::Internal
+                                                          : ui::DisplayConnectionType::External;
     return Error::NONE;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 4c7f284..e7bf286 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -18,9 +18,9 @@
 
 #include <gui/HdrMetadata.h>
 #include <math/mat4.h>
-#include <ui/DisplayInfo.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
+#include <ui/StaticDisplayInfo.h>
 #include <utils/Log.h>
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
@@ -104,7 +104,7 @@
             hal::DisplayRequest* outDisplayRequests,
             std::unordered_map<Layer*, hal::LayerRequest>* outLayerRequests) = 0;
     [[clang::warn_unused_result]] virtual hal::Error getConnectionType(
-            android::DisplayConnectionType*) const = 0;
+            ui::DisplayConnectionType*) const = 0;
     [[clang::warn_unused_result]] virtual hal::Error supportsDoze(bool* outSupport) const = 0;
     [[clang::warn_unused_result]] virtual hal::Error getHdrCapabilities(
             android::HdrCapabilities* outCapabilities) const = 0;
@@ -175,7 +175,7 @@
     hal::Error getRequests(
             hal::DisplayRequest* outDisplayRequests,
             std::unordered_map<Layer*, hal::LayerRequest>* outLayerRequests) override;
-    hal::Error getConnectionType(android::DisplayConnectionType*) const override;
+    hal::Error getConnectionType(ui::DisplayConnectionType*) const override;
     hal::Error supportsDoze(bool* outSupport) const override;
     hal::Error getHdrCapabilities(android::HdrCapabilities* outCapabilities) const override;
     hal::Error getDisplayedContentSamplingAttributes(hal::PixelFormat* outFormat,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index b9a8e4b..ccfaa76 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -369,16 +369,16 @@
 
 // Composer 2.4
 
-DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
-    RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal);
+ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const {
+    RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal);
     const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay;
 
-    DisplayConnectionType type;
+    ui::DisplayConnectionType type;
     const auto error = hwcDisplay->getConnectionType(&type);
 
     const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId
-            ? DisplayConnectionType::Internal
-            : DisplayConnectionType::External;
+            ? ui::DisplayConnectionType::Internal
+            : ui::DisplayConnectionType::External;
 
     RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
     return type;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index f9c8e2e..cf6bc68 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -204,7 +204,7 @@
                                         ui::RenderIntent) = 0;
 
     // Composer 2.4
-    virtual DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0;
+    virtual ui::DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0;
     virtual bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const = 0;
     virtual status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
                                            nsecs_t* outVsyncPeriod) const = 0;
@@ -335,7 +335,7 @@
     status_t setActiveColorMode(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent) override;
 
     // Composer 2.4
-    DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override;
+    ui::DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override;
     bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const override;
     status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
                                    nsecs_t* outVsyncPeriod) const override;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index a03f793..de11c16 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -64,7 +64,7 @@
 using RefreshRate = RefreshRateConfigs::RefreshRate;
 
 std::string RefreshRate::toString() const {
-    return base::StringPrintf("{id=%zu, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}",
+    return base::StringPrintf("{id=%d, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}",
                               getModeId().value(), mode->getHwcId(), getFps().getValue(),
                               mode->getWidth(), mode->getHeight(), getModeGroup());
 }
@@ -89,7 +89,7 @@
 }
 
 std::string RefreshRateConfigs::Policy::toString() const {
-    return base::StringPrintf("default mode ID: %zu, allowGroupSwitching = %d"
+    return base::StringPrintf("default mode ID: %d, allowGroupSwitching = %d"
                               ", primary range: %s, app request range: %s",
                               defaultMode.value(), allowGroupSwitching,
                               primaryRange.toString().c_str(), appRequestRange.toString().c_str());
@@ -724,7 +724,7 @@
     outRefreshRates->reserve(mRefreshRates.size());
     for (const auto& [type, refreshRate] : mRefreshRates) {
         if (shouldAddRefreshRate(*refreshRate)) {
-            ALOGV("getSortedRefreshRateListLocked: mode %zu added to list policy",
+            ALOGV("getSortedRefreshRateListLocked: mode %d added to list policy",
                   refreshRate->modeId.value());
             outRefreshRates->push_back(refreshRate.get());
         }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7fada82..ecf5358 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -68,12 +68,13 @@
 #include <ui/ColorSpace.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayId.h>
-#include <ui/DisplayInfo.h>
 #include <ui/DisplayMode.h>
 #include <ui/DisplayStatInfo.h>
 #include <ui/DisplayState.h>
+#include <ui/DynamicDisplayInfo.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
+#include <ui/StaticDisplayInfo.h>
 #include <utils/StopWatch.h>
 #include <utils/String16.h>
 #include <utils/String8.h>
@@ -854,7 +855,8 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& displayToken, DisplayInfo* info) {
+status_t SurfaceFlinger::getStaticDisplayInfo(const sp<IBinder>& displayToken,
+                                              ui::StaticDisplayInfo* info) {
     if (!displayToken || !info) {
         return BAD_VALUE;
     }
@@ -875,7 +877,7 @@
     if (mEmulatedDisplayDensity) {
         info->density = mEmulatedDisplayDensity;
     } else {
-        info->density = info->connectionType == DisplayConnectionType::Internal
+        info->density = info->connectionType == ui::DisplayConnectionType::Internal
                 ? mInternalDisplayDensity
                 : FALLBACK_DENSITY;
     }
@@ -887,9 +889,9 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::getDisplayModes(const sp<IBinder>& displayToken,
-                                         Vector<ui::DisplayMode>* modes) {
-    if (!displayToken || !modes) {
+status_t SurfaceFlinger::getDynamicDisplayInfo(const sp<IBinder>& displayToken,
+                                               ui::DynamicDisplayInfo* info) {
+    if (!displayToken || !info) {
         return BAD_VALUE;
     }
 
@@ -900,16 +902,25 @@
         return NAME_NOT_FOUND;
     }
 
-    modes->clear();
+    info->activeDisplayModeId = static_cast<int32_t>(display->getActiveMode()->getId().value());
+    if (display->isPrimary()) {
+        if (const auto mode = getDesiredActiveMode()) {
+            info->activeDisplayModeId = static_cast<int32_t>(mode->modeId.value());
+        }
+    }
 
-    for (const auto& supportedMode : display->getSupportedModes()) {
-        ui::DisplayMode mode;
+    const auto& supportedModes = display->getSupportedModes();
+    info->supportedDisplayModes.clear();
+    info->supportedDisplayModes.reserve(supportedModes.size());
+    for (const auto& mode : supportedModes) {
+        ui::DisplayMode outMode;
+        outMode.id = static_cast<int32_t>(mode->getId().value());
 
-        auto width = supportedMode->getWidth();
-        auto height = supportedMode->getHeight();
+        auto width = mode->getWidth();
+        auto height = mode->getHeight();
 
-        auto xDpi = supportedMode->getDpiX();
-        auto yDpi = supportedMode->getDpiY();
+        auto xDpi = mode->getDpiX();
+        auto yDpi = mode->getDpiY();
 
         if (display->isPrimary() &&
             (internalDisplayOrientation == ui::ROTATION_90 ||
@@ -918,24 +929,24 @@
             std::swap(xDpi, yDpi);
         }
 
-        mode.resolution = ui::Size(width, height);
+        outMode.resolution = ui::Size(width, height);
 
         if (mEmulatedDisplayDensity) {
-            mode.xDpi = mEmulatedDisplayDensity;
-            mode.yDpi = mEmulatedDisplayDensity;
+            outMode.xDpi = mEmulatedDisplayDensity;
+            outMode.yDpi = mEmulatedDisplayDensity;
         } else {
-            mode.xDpi = xDpi;
-            mode.yDpi = yDpi;
+            outMode.xDpi = xDpi;
+            outMode.yDpi = yDpi;
         }
 
-        const nsecs_t period = supportedMode->getVsyncPeriod();
-        mode.refreshRate = Fps::fromPeriodNsecs(period).getValue();
+        const nsecs_t period = mode->getVsyncPeriod();
+        outMode.refreshRate = Fps::fromPeriodNsecs(period).getValue();
 
         const auto vsyncConfigSet =
-                mVsyncConfiguration->getConfigsForRefreshRate(Fps(mode.refreshRate));
-        mode.appVsyncOffset = vsyncConfigSet.late.appOffset;
-        mode.sfVsyncOffset = vsyncConfigSet.late.sfOffset;
-        mode.group = supportedMode->getGroup();
+                mVsyncConfiguration->getConfigsForRefreshRate(Fps(outMode.refreshRate));
+        outMode.appVsyncOffset = vsyncConfigSet.late.appOffset;
+        outMode.sfVsyncOffset = vsyncConfigSet.late.sfOffset;
+        outMode.group = mode->getGroup();
 
         // This is how far in advance a buffer must be queued for
         // presentation at a given time.  If you want a buffer to appear
@@ -949,11 +960,15 @@
         //
         // We add an additional 1ms to allow for processing time and
         // differences between the ideal and actual refresh rate.
-        mode.presentationDeadline = period - mode.sfVsyncOffset + 1000000;
+        outMode.presentationDeadline = period - outMode.sfVsyncOffset + 1000000;
 
-        modes->push_back(mode);
+        info->supportedDisplayModes.push_back(outMode);
     }
 
+    info->activeColorMode = display->getCompositionDisplay()->getState().colorMode;
+    info->supportedColorModes = getDisplayColorModes(display->getPhysicalId());
+
+    info->hdrCapabilities = display->getHdrCapabilities();
     return NO_ERROR;
 }
 
@@ -966,31 +981,6 @@
     return NO_ERROR;
 }
 
-int SurfaceFlinger::getActiveDisplayModeId(const sp<IBinder>& displayToken) {
-    int activeMode;
-    bool isPrimary;
-
-    {
-        Mutex::Autolock lock(mStateLock);
-
-        if (const auto display = getDisplayDeviceLocked(displayToken)) {
-            activeMode = display->getActiveMode()->getId().value();
-            isPrimary = display->isPrimary();
-        } else {
-            ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
-            return NAME_NOT_FOUND;
-        }
-    }
-
-    if (isPrimary) {
-        if (const auto mode = getDesiredActiveMode()) {
-            return mode->modeId.value();
-        }
-    }
-
-    return activeMode;
-}
-
 void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) {
     ATRACE_CALL();
     auto refreshRate = mRefreshRateConfigs->getRefreshRateFromModeId(info.modeId);
@@ -1082,7 +1072,7 @@
 
     const auto upcomingMode = display->getMode(mUpcomingActiveMode.modeId);
     if (!upcomingMode) {
-        ALOGW("Upcoming active mode is no longer supported. Mode ID = %zu",
+        ALOGW("Upcoming active mode is no longer supported. Mode ID = %d",
               mUpcomingActiveMode.modeId.value());
         // TODO(b/159590486) Handle the error better. Some parts of SurfaceFlinger may
         // have been already updated with the upcoming active mode.
@@ -1142,13 +1132,13 @@
     const auto display = getDefaultDisplayDeviceLocked();
     const auto desiredMode = display->getMode(desiredActiveMode->modeId);
     if (!desiredMode) {
-        ALOGW("Desired display mode is no longer supported. Mode ID = %zu",
+        ALOGW("Desired display mode is no longer supported. Mode ID = %d",
               desiredActiveMode->modeId.value());
         clearDesiredActiveModeState();
         return;
     }
     const auto refreshRate = desiredMode->getFps();
-    ALOGV("%s changing active mode to %zu(%s)", __FUNCTION__, desiredMode->getId().value(),
+    ALOGV("%s changing active mode to %d(%s)", __FUNCTION__, desiredMode->getId().value(),
           to_string(refreshRate).c_str());
 
     if (!display || display->getActiveMode()->getId() == desiredActiveMode->modeId) {
@@ -1190,39 +1180,20 @@
     mSetActiveModePending = true;
 }
 
-status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
-                                              Vector<ColorMode>* outColorModes) {
-    if (!displayToken || !outColorModes) {
-        return BAD_VALUE;
-    }
-
-    std::vector<ColorMode> modes;
-    bool isInternalDisplay = false;
-    {
-        ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
-
-        const auto displayId = getPhysicalDisplayIdLocked(displayToken);
-        if (!displayId) {
-            return NAME_NOT_FOUND;
-        }
-
-        modes = getHwComposer().getColorModes(*displayId);
-        isInternalDisplay = displayId == getInternalDisplayIdLocked();
-    }
-    outColorModes->clear();
+std::vector<ColorMode> SurfaceFlinger::getDisplayColorModes(PhysicalDisplayId displayId) {
+    auto modes = getHwComposer().getColorModes(displayId);
+    bool isInternalDisplay = displayId == getInternalDisplayIdLocked();
 
     // If it's built-in display and the configuration claims it's not wide color capable,
     // filter out all wide color modes. The typical reason why this happens is that the
     // hardware is not good enough to support GPU composition of wide color, and thus the
     // OEMs choose to disable this capability.
     if (isInternalDisplay && !hasWideColorDisplay) {
-        std::remove_copy_if(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes),
-                            isWideColorMode);
-    } else {
-        std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
+        const auto newEnd = std::remove_if(modes.begin(), modes.end(), isWideColorMode);
+        modes.erase(newEnd, modes.end());
     }
 
-    return NO_ERROR;
+    return modes;
 }
 
 status_t SurfaceFlinger::getDisplayNativePrimaries(const sp<IBinder>& displayToken,
@@ -1240,19 +1211,14 @@
     return NO_ERROR;
 }
 
-ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& displayToken) {
-    Mutex::Autolock lock(mStateLock);
-
-    if (const auto display = getDisplayDeviceLocked(displayToken)) {
-        return display->getCompositionDisplay()->getState().colorMode;
-    }
-    return static_cast<ColorMode>(BAD_VALUE);
-}
-
 status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) {
     schedule([=]() MAIN_THREAD {
-        Vector<ColorMode> modes;
-        getDisplayColorModes(displayToken, &modes);
+        const auto displayId = getPhysicalDisplayIdLocked(displayToken);
+        if (!displayId) {
+            ALOGE("Invalid display token %p", displayToken.get());
+            return;
+        }
+        const auto modes = getDisplayColorModes(*displayId);
         bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes);
         if (mode < ColorMode::NATIVE || !exists) {
             ALOGE("Attempt to set invalid active color mode %s (%d) for display token %p",
@@ -1349,28 +1315,6 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& displayToken,
-                                            HdrCapabilities* outCapabilities) const {
-    Mutex::Autolock lock(mStateLock);
-
-    const auto display = getDisplayDeviceLocked(displayToken);
-    if (!display) {
-        ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
-        return NAME_NOT_FOUND;
-    }
-
-    // At this point the DisplayDevice should already be set up,
-    // meaning the luminance information is already queried from
-    // hardware composer and stored properly.
-    const HdrCapabilities& capabilities = display->getHdrCapabilities();
-    *outCapabilities = HdrCapabilities(capabilities.getSupportedHdrTypes(),
-                                       capabilities.getDesiredMaxLuminance(),
-                                       capabilities.getDesiredMaxAverageLuminance(),
-                                       capabilities.getDesiredMinLuminance());
-
-    return NO_ERROR;
-}
-
 status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp<IBinder>& displayToken,
                                                                ui::PixelFormat* outFormat,
                                                                ui::Dataspace* outDataspace,
@@ -1640,7 +1584,7 @@
 
     // Don't do any updating if the current fps is the same as the new one.
     if (!isDisplayModeAllowed(refreshRate.getModeId())) {
-        ALOGV("Skipping mode %zu as it is not part of allowed modes",
+        ALOGV("Skipping mode %d as it is not part of allowed modes",
               refreshRate.getModeId().value());
         return;
     }
@@ -2360,7 +2304,7 @@
 DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId displayId) const {
     const auto hwcModes = getHwComposer().getModes(displayId);
     DisplayModes modes;
-    size_t nextModeId = 0;
+    int32_t nextModeId = 0;
     for (const auto& hwcMode : hwcModes) {
         modes.push_back(DisplayMode::Builder(hwcMode.hwcId)
                                 .setId(DisplayModeId{nextModeId++})
@@ -5013,7 +4957,8 @@
         case GET_PHYSICAL_DISPLAY_TOKEN:
         case GET_DISPLAY_COLOR_MODES:
         case GET_DISPLAY_NATIVE_PRIMARIES:
-        case GET_DISPLAY_INFO:
+        case GET_STATIC_DISPLAY_INFO:
+        case GET_DYNAMIC_DISPLAY_INFO:
         case GET_DISPLAY_MODES:
         case GET_DISPLAY_STATE:
         case GET_DISPLAY_STATS:
@@ -6141,27 +6086,25 @@
             ? mRefreshRateConfigs->getRefreshRateFromModeId(*modeId)
             // NOTE: Choose the default mode ID, if Scheduler doesn't have one in mind.
             : mRefreshRateConfigs->getRefreshRateFromModeId(currentPolicy.defaultMode);
-    ALOGV("trying to switch to Scheduler preferred mode %zu (%s)",
+    ALOGV("trying to switch to Scheduler preferred mode %d (%s)",
           preferredRefreshRate.getModeId().value(), preferredRefreshRate.getName().c_str());
 
     if (isDisplayModeAllowed(preferredRefreshRate.getModeId())) {
-        ALOGV("switching to Scheduler preferred display mode %zu",
+        ALOGV("switching to Scheduler preferred display mode %d",
               preferredRefreshRate.getModeId().value());
         setDesiredActiveMode({preferredRefreshRate.getModeId(), Scheduler::ModeEvent::Changed});
     } else {
-        LOG_ALWAYS_FATAL("Desired display mode not allowed: %zu",
+        LOG_ALWAYS_FATAL("Desired display mode not allowed: %d",
                          preferredRefreshRate.getModeId().value());
     }
 
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
-                                                    size_t defaultMode, bool allowGroupSwitching,
-                                                    float primaryRefreshRateMin,
-                                                    float primaryRefreshRateMax,
-                                                    float appRequestRefreshRateMin,
-                                                    float appRequestRefreshRateMax) {
+status_t SurfaceFlinger::setDesiredDisplayModeSpecs(
+        const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching,
+        float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin,
+        float appRequestRefreshRateMax) {
     ATRACE_CALL();
 
     if (!displayToken) {
@@ -6192,10 +6135,13 @@
     return future.get();
 }
 
-status_t SurfaceFlinger::getDesiredDisplayModeSpecs(
-        const sp<IBinder>& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching,
-        float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax,
-        float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) {
+status_t SurfaceFlinger::getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                                    ui::DisplayModeId* outDefaultMode,
+                                                    bool* outAllowGroupSwitching,
+                                                    float* outPrimaryRefreshRateMin,
+                                                    float* outPrimaryRefreshRateMax,
+                                                    float* outAppRequestRefreshRateMin,
+                                                    float* outAppRequestRefreshRateMax) {
     ATRACE_CALL();
 
     if (!displayToken || !outDefaultMode || !outPrimaryRefreshRateMin ||
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a62d0b9..21cd2a5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -552,14 +552,14 @@
                            const sp<IScreenCaptureListener>& captureListener) override;
 
     status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
-    status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*) override;
-    status_t getDisplayInfo(const sp<IBinder>& displayToken, DisplayInfo*) override;
-    status_t getDisplayModes(const sp<IBinder>& displayToken, Vector<ui::DisplayMode>*) override;
-    int getActiveDisplayModeId(const sp<IBinder>& displayToken) override;
-    status_t getDisplayColorModes(const sp<IBinder>& displayToken, Vector<ui::ColorMode>*) override;
+    status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*)
+            EXCLUDES(mStateLock) override;
+    status_t getStaticDisplayInfo(const sp<IBinder>& displayToken, ui::StaticDisplayInfo*)
+            EXCLUDES(mStateLock) override;
+    status_t getDynamicDisplayInfo(const sp<IBinder>& displayToken, ui::DynamicDisplayInfo*)
+            EXCLUDES(mStateLock) override;
     status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken,
                                        ui::DisplayPrimaries&) override;
-    ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken) override;
     status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
     status_t getAutoLowLatencyModeSupport(const sp<IBinder>& displayToken,
                                           bool* outSupported) const override;
@@ -570,8 +570,6 @@
     void setPowerMode(const sp<IBinder>& displayToken, int mode) override;
     status_t clearAnimationFrameStats() override;
     status_t getAnimationFrameStats(FrameStats* outStats) const override;
-    status_t getHdrCapabilities(const sp<IBinder>& displayToken,
-                                HdrCapabilities* outCapabilities) const override;
     status_t enableVSyncInjections(bool enable) override;
     status_t injectVSync(nsecs_t when) override;
     status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override;
@@ -594,11 +592,13 @@
     status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
                                        const sp<IRegionSamplingListener>& listener) override;
     status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override;
-    status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t displayModeId,
-                                        bool allowGroupSwitching, float primaryRefreshRateMin,
-                                        float primaryRefreshRateMax, float appRequestRefreshRateMin,
+    status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                        ui::DisplayModeId displayModeId, bool allowGroupSwitching,
+                                        float primaryRefreshRateMin, float primaryRefreshRateMax,
+                                        float appRequestRefreshRateMin,
                                         float appRequestRefreshRateMax) override;
-    status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t* outDefaultMode,
+    status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                        ui::DisplayModeId* outDefaultMode,
                                         bool* outAllowGroupSwitching,
                                         float* outPrimaryRefreshRateMin,
                                         float* outPrimaryRefreshRateMax,
@@ -1054,6 +1054,9 @@
         return std::nullopt;
     }
 
+    std::vector<ui::ColorMode> getDisplayColorModes(PhysicalDisplayId displayId)
+            REQUIRES(mStateLock);
+
     static int calculateExtraBufferCount(Fps maxSupportedRefreshRate,
                                          std::chrono::nanoseconds presentLatency);
 
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index 53e37d8..6246321 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -26,6 +26,7 @@
 #include <private/android_filesystem_config.h>
 #include <private/gui/ComposerService.h>
 #include <ui/DisplayMode.h>
+#include <ui/DynamicDisplayInfo.h>
 #include <utils/String8.h>
 #include <functional>
 #include "utils/ScreenshotUtils.h"
@@ -188,19 +189,15 @@
     ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
 
     Vector<ui::DisplayMode> modes;
-    ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
-
-    ASSERT_TRUE(SurfaceComposerClient::getActiveDisplayModeId(display) >= 0);
-
-    ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
-              SurfaceComposerClient::getActiveColorMode(display));
+    ui::DynamicDisplayInfo info;
+    ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info));
 }
 
-TEST_F(CredentialsTest, GetDisplayColorModesTest) {
+TEST_F(CredentialsTest, GetDynamicDisplayInfoTest) {
     const auto display = SurfaceComposerClient::getInternalDisplayToken();
     std::function<status_t()> condition = [=]() {
-        Vector<ui::ColorMode> outColorModes;
-        return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
+        ui::DynamicDisplayInfo info;
+        return SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
     };
     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
 }
@@ -216,7 +213,7 @@
 
 TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
     const auto display = SurfaceComposerClient::getInternalDisplayToken();
-    size_t defaultMode;
+    ui::DisplayModeId defaultMode;
     bool allowGroupSwitching;
     float primaryFpsMin;
     float primaryFpsMax;
@@ -355,8 +352,9 @@
     status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
     ASSERT_EQ(NO_ERROR, error);
     bool hasWideColorMode = false;
-    Vector<ColorMode> colorModes;
-    SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
+    ui::DynamicDisplayInfo info;
+    SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
+    const auto& colorModes = info.supportedColorModes;
     for (ColorMode colorMode : colorModes) {
         switch (colorMode) {
             case ColorMode::DISPLAY_P3:
@@ -384,7 +382,9 @@
 TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
     const auto display = SurfaceComposerClient::getInternalDisplayToken();
     ASSERT_FALSE(display == nullptr);
-    ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display);
+    ui::DynamicDisplayInfo info;
+    SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
+    ColorMode colorMode = info.activeColorMode;
     ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
 }
 
diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
index 9f025a6..2dc96b8 100644
--- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp
+++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
@@ -23,6 +23,7 @@
 #include <gui/SurfaceComposerClient.h>
 #include <private/gui/ComposerService.h>
 #include <ui/DisplayMode.h>
+#include <ui/DynamicDisplayInfo.h>
 #include <utils/Errors.h>
 #include <utils/Vector.h>
 
@@ -38,7 +39,7 @@
  */
 class RefreshRateRangeTest : public ::testing::Test {
 private:
-    size_t initialDefaultMode;
+    ui::DisplayModeId initialDefaultMode;
     bool initialAllowGroupSwitching;
     float initialPrimaryMin;
     float initialPrimaryMax;
@@ -76,20 +77,21 @@
 };
 
 TEST_F(RefreshRateRangeTest, setAllConfigs) {
-    Vector<ui::DisplayMode> modes;
-    status_t res = SurfaceComposerClient::getDisplayModes(mDisplayToken, &modes);
+    ui::DynamicDisplayInfo info;
+    status_t res = SurfaceComposerClient::getDynamicDisplayInfo(mDisplayToken, &info);
+    const auto& modes = info.supportedDisplayModes;
     ASSERT_EQ(res, NO_ERROR);
     ASSERT_GT(modes.size(), 0);
 
     for (size_t i = 0; i < modes.size(); i++) {
-        res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, i, false,
+        res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, modes[i].id, false,
                                                                 modes[i].refreshRate,
                                                                 modes[i].refreshRate,
                                                                 modes[i].refreshRate,
                                                                 modes[i].refreshRate);
         ASSERT_EQ(res, NO_ERROR);
 
-        size_t defaultConfig;
+        ui::DisplayModeId defaultConfig;
         bool allowGroupSwitching;
         float primaryRefreshRateMin;
         float primaryRefreshRateMax;
@@ -116,7 +118,7 @@
             SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, 0, allowGroupSwitching,
                                                               0.f, 90.f, 0.f, 90.f);
     ASSERT_EQ(res, NO_ERROR);
-    size_t defaultConfig;
+    ui::DisplayModeId defaultConfig;
     bool newAllowGroupSwitching;
     float primaryRefreshRateMin;
     float primaryRefreshRateMax;
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 56e1ae9..11bd9eb 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -44,6 +44,7 @@
 #include <log/log.h>
 #include <private/gui/ComposerService.h>
 #include <ui/DisplayMode.h>
+#include <ui/DynamicDisplayInfo.h>
 #include <utils/Looper.h>
 
 #include <gmock/gmock.h>
@@ -432,8 +433,9 @@
             }
         }
 
-        Vector<ui::DisplayMode> modes;
-        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+        ui::DynamicDisplayInfo info;
+        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info));
+        const auto& modes = info.supportedDisplayModes;
         EXPECT_EQ(modes.size(), 2);
 
         // change active mode
@@ -539,8 +541,9 @@
             }
         }
 
-        Vector<ui::DisplayMode> modes;
-        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+        ui::DynamicDisplayInfo info;
+        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info));
+        const auto& modes = info.supportedDisplayModes;
         EXPECT_EQ(modes.size(), 2);
 
         // change active mode
@@ -655,8 +658,9 @@
             }
         }
 
-        Vector<ui::DisplayMode> modes;
-        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+        ui::DynamicDisplayInfo info;
+        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info));
+        const auto& modes = info.supportedDisplayModes;
         EXPECT_EQ(modes.size(), 4);
 
         // change active mode to 800x1600@90Hz
@@ -884,8 +888,9 @@
             EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
             EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate);
 
-            Vector<ui::DisplayMode> modes;
-            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+            ui::DynamicDisplayInfo info;
+            EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info));
+            const auto& modes = info.supportedDisplayModes;
             EXPECT_EQ(modes.size(), 1);
         }
 
@@ -923,8 +928,9 @@
             EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate);
         }
 
-        Vector<ui::DisplayMode> modes;
-        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+        ui::DynamicDisplayInfo info;
+        EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info));
+        const auto& modes = info.supportedDisplayModes;
         EXPECT_EQ(modes.size(), 3);
 
         EXPECT_EQ(ui::Size(800, 1600), modes[0].resolution);
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index b696a6d..256be27 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -286,7 +286,7 @@
 
         auto ceDisplayArgs =
                 compositionengine::DisplayCreationArgsBuilder()
-                        .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal})
+                        .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal})
                         .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
                         .setIsSecure(Derived::IS_SECURE)
                         .setLayerStackId(DEFAULT_LAYER_STACK)
@@ -300,7 +300,7 @@
                                                        ceDisplayArgs);
 
         test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
-                                                   DisplayConnectionType::Internal, HWC_DISPLAY,
+                                                   ui::DisplayConnectionType::Internal, HWC_DISPLAY,
                                                    true /* isPrimary */)
                                  .setDisplaySurface(test->mDisplaySurface)
                                  .setNativeWindow(test->mNativeWindow)
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 9069200..a3e8108 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -139,14 +139,14 @@
             createDisplay(mFlinger.getCompositionEngine(),
                           compositionengine::DisplayCreationArgsBuilder()
                                   .setPhysical(
-                                          {DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal})
+                                          {DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal})
                                   .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
                                   .setPowerAdvisor(&mPowerAdvisor)
                                   .build());
 
-    auto injector =
-            FakeDisplayDeviceInjector(mFlinger, compositionDisplay, DisplayConnectionType::Internal,
-                                      DEFAULT_DISPLAY_HWC_DISPLAY_ID, true /* isPrimary */);
+    auto injector = FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
+                                              ui::DisplayConnectionType::Internal,
+                                              DEFAULT_DISPLAY_HWC_DISPLAY_ID, true /* isPrimary */);
 
     injector.setNativeWindow(mNativeWindow);
     if (injectExtra) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 1664301..d68fff6 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -202,12 +202,13 @@
 
 template <typename>
 struct DisplayConnectionTypeGetter {
-    static constexpr std::optional<DisplayConnectionType> value;
+    static constexpr std::optional<ui::DisplayConnectionType> value;
 };
 
 template <typename PhysicalDisplay>
 struct DisplayConnectionTypeGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
-    static constexpr std::optional<DisplayConnectionType> value = PhysicalDisplay::CONNECTION_TYPE;
+    static constexpr std::optional<ui::DisplayConnectionType> value =
+            PhysicalDisplay::CONNECTION_TYPE;
 };
 
 template <typename>
@@ -263,7 +264,7 @@
     static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
         auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder();
         if (auto displayId = PhysicalDisplayId::tryCast(DISPLAY_ID::get())) {
-            ceDisplayArgs.setPhysical({*displayId, DisplayConnectionType::Internal});
+            ceDisplayArgs.setPhysical({*displayId, ui::DisplayConnectionType::Internal});
         } else {
             // We turn off the use of HwcVirtualDisplays, to prevent Composition Engine
             // from calling into HWComposer. This way all virtual displays will get
@@ -457,7 +458,7 @@
 
     static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
         constexpr auto CONNECTION_TYPE =
-                PhysicalDisplay::CONNECTION_TYPE == DisplayConnectionType::Internal
+                PhysicalDisplay::CONNECTION_TYPE == ui::DisplayConnectionType::Internal
                 ? IComposerClient::DisplayConnectionType::INTERNAL
                 : IComposerClient::DisplayConnectionType::EXTERNAL;
 
@@ -504,7 +505,7 @@
 
 template <bool hasIdentificationData>
 struct PrimaryDisplay {
-    static constexpr auto CONNECTION_TYPE = DisplayConnectionType::Internal;
+    static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::Internal;
     static constexpr Primary PRIMARY = Primary::TRUE;
     static constexpr uint8_t PORT = 255;
     static constexpr HWDisplayId HWC_DISPLAY_ID = 1001;
@@ -514,7 +515,7 @@
 
 template <bool hasIdentificationData>
 struct ExternalDisplay {
-    static constexpr auto CONNECTION_TYPE = DisplayConnectionType::External;
+    static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::External;
     static constexpr Primary PRIMARY = Primary::FALSE;
     static constexpr uint8_t PORT = 254;
     static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index dee13d6..2ba6490 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -634,7 +634,7 @@
     public:
         FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger,
                                   std::shared_ptr<compositionengine::Display> compositionDisplay,
-                                  std::optional<DisplayConnectionType> connectionType,
+                                  std::optional<ui::DisplayConnectionType> connectionType,
                                   std::optional<hal::HWDisplayId> hwcDisplayId, bool isPrimary)
               : mFlinger(flinger),
                 mCreationArgs(flinger.mFlinger.get(), flinger.mFlinger->getHwComposer(),