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