SF: Move color modes to DisplaySnapshot

Bug: 241285876
Test: dumpsys SurfaceFlinger --displays
Test: dumpsys SurfaceFlinger --wide-color
Change-Id: Ib546cd66950155102dbe021a2a764ad2c47d27fa
diff --git a/services/surfaceflinger/Display/DisplaySnapshot.cpp b/services/surfaceflinger/Display/DisplaySnapshot.cpp
index fca3a3d..0c7a58e 100644
--- a/services/surfaceflinger/Display/DisplaySnapshot.cpp
+++ b/services/surfaceflinger/Display/DisplaySnapshot.cpp
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
+#include <algorithm>
 #include <functional>
 #include <utility>
 
 #include <ftl/algorithm.h>
 #include <ftl/enum.h>
+#include <ui/DebugUtils.h>
 
 #include "DisplaySnapshot.h"
 
@@ -26,11 +28,12 @@
 
 DisplaySnapshot::DisplaySnapshot(PhysicalDisplayId displayId,
                                  ui::DisplayConnectionType connectionType,
-                                 DisplayModes&& displayModes,
+                                 DisplayModes&& displayModes, ui::ColorModes&& colorModes,
                                  std::optional<DeviceProductInfo>&& deviceProductInfo)
       : mDisplayId(displayId),
         mConnectionType(connectionType),
         mDisplayModes(std::move(displayModes)),
+        mColorModes(std::move(colorModes)),
         mDeviceProductInfo(std::move(deviceProductInfo)) {}
 
 std::optional<DisplayModeId> DisplaySnapshot::translateModeId(hal::HWConfigId hwcId) const {
@@ -41,10 +44,34 @@
             .transform(&ftl::to_key<DisplayModes>);
 }
 
+ui::ColorModes DisplaySnapshot::filterColorModes(bool supportsWideColor) const {
+    ui::ColorModes modes = mColorModes;
+
+    // If the display is internal 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 (mConnectionType == ui::DisplayConnectionType::Internal && !supportsWideColor) {
+        const auto it = std::remove_if(modes.begin(), modes.end(), ui::isWideColorMode);
+        modes.erase(it, modes.end());
+    }
+
+    return modes;
+}
+
 void DisplaySnapshot::dump(utils::Dumper& dumper) const {
     using namespace std::string_view_literals;
 
     dumper.dump("connectionType"sv, ftl::enum_string(mConnectionType));
+
+    dumper.dump("colorModes"sv);
+    {
+        utils::Dumper::Indent indent(dumper);
+        for (const auto mode : mColorModes) {
+            dumper.dump({}, decodeColorMode(mode));
+        }
+    }
+
     dumper.dump("deviceProductInfo"sv, mDeviceProductInfo);
 }
 
diff --git a/services/surfaceflinger/Display/DisplaySnapshot.h b/services/surfaceflinger/Display/DisplaySnapshot.h
index 3f34e39..23471f5 100644
--- a/services/surfaceflinger/Display/DisplaySnapshot.h
+++ b/services/surfaceflinger/Display/DisplaySnapshot.h
@@ -18,6 +18,7 @@
 
 #include <optional>
 
+#include <ui/ColorMode.h>
 #include <ui/DisplayId.h>
 #include <ui/StaticDisplayInfo.h>
 
@@ -29,7 +30,7 @@
 // Immutable state of a physical display, captured on hotplug.
 class DisplaySnapshot {
 public:
-    DisplaySnapshot(PhysicalDisplayId, ui::DisplayConnectionType, DisplayModes&&,
+    DisplaySnapshot(PhysicalDisplayId, ui::DisplayConnectionType, DisplayModes&&, ui::ColorModes&&,
                     std::optional<DeviceProductInfo>&&);
 
     DisplaySnapshot(const DisplaySnapshot&) = delete;
@@ -41,8 +42,11 @@
     std::optional<DisplayModeId> translateModeId(hal::HWConfigId) const;
 
     const auto& displayModes() const { return mDisplayModes; }
+    const auto& colorModes() const { return mColorModes; }
     const auto& deviceProductInfo() const { return mDeviceProductInfo; }
 
+    ui::ColorModes filterColorModes(bool supportsWideColor) const;
+
     void dump(utils::Dumper&) const;
 
 private:
@@ -51,6 +55,7 @@
 
     // Effectively const except in move constructor.
     DisplayModes mDisplayModes;
+    ui::ColorModes mColorModes;
     std::optional<DeviceProductInfo> mDeviceProductInfo;
 };