[SurfaceFlinger] Filter out wide color modes for built-in display when necessary.

OEMs can choose whether to advertize the built-in display is wide color capable
regardless of whether hardware composer returns wide color modes or not. This
patch makes sure those this configuration is taken into account when we return
the color modes of the built-in display. Otherwise those devices will fail the
Display CTS tests.

BUG: 133010445
Test: Boot. Verified with Pixel 3.
Change-Id: Id70c39a4d274400f2c66b0a04728524051cb5c6a
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 820ccc5..dd75868 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1049,6 +1049,7 @@
     }
 
     std::vector<ColorMode> modes;
+    bool isInternalDisplay = false;
     {
         ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
 
@@ -1058,9 +1059,20 @@
         }
 
         modes = getHwComposer().getColorModes(*displayId);
+        isInternalDisplay = displayId == getInternalDisplayIdLocked();
     }
     outColorModes->clear();
-    std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
+
+    // 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));
+    }
 
     return NO_ERROR;
 }
@@ -1207,6 +1219,13 @@
     if (!display) {
         return BAD_VALUE;
     }
+
+    // Use hasWideColorDisplay to override built-in display.
+    const auto displayId = display->getId();
+    if (displayId && displayId == getInternalDisplayIdLocked()) {
+        *outIsWideColorDisplay = hasWideColorDisplay;
+        return NO_ERROR;
+    }
     *outIsWideColorDisplay = display->hasWideColorGamut();
     return NO_ERROR;
 }
@@ -4746,7 +4765,7 @@
 }
 
 void SurfaceFlinger::dumpWideColorInfo(std::string& result) const {
-    StringAppendF(&result, "Device has wide color display: %d\n", hasWideColorDisplay);
+    StringAppendF(&result, "Device has wide color built-in display: %d\n", hasWideColorDisplay);
     StringAppendF(&result, "Device uses color management: %d\n", useColorManagement);
     StringAppendF(&result, "DisplayColorSetting: %s\n",
                   decodeDisplayColorSetting(mDisplayColorSetting).c_str());