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