[Screenshot] Accept data space and pixel format for screenshot.

Previously we always take screenshot in SRGB data space. It's been working well
since the screen only has sRGB color. However, since we are moving towards
wider color, we can't make this assumption any more. Thus we need to pass the
data space and pixel format of the screenshot buffer into SurfaceFlinger and
render screenshot in the desired data space and pixel format.

BUG: 111436479
BUG: 116112787
Test: Build, flash, boot and take screenshot, observe there's no color shift.
Test: Take screenshot, verified the color profile is correct of the png.
Change-Id: I9b1a1c878f8099715c2a2c296aaf3419ca6e9bd5
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index d334f96..8fa2980 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -31,6 +31,7 @@
 #include <gui/ISurfaceComposer.h>
 
 #include <ui/DisplayInfo.h>
+#include <ui/GraphicTypes.h>
 #include <ui/PixelFormat.h>
 
 #include <system/graphics.h>
@@ -74,12 +75,12 @@
     }
 }
 
-static sk_sp<SkColorSpace> dataSpaceToColorSpace(android_dataspace d)
+static sk_sp<SkColorSpace> dataSpaceToColorSpace(ui::Dataspace d)
 {
     switch (d) {
-        case HAL_DATASPACE_V0_SRGB:
+        case ui::Dataspace::V0_SRGB:
             return SkColorSpace::MakeSRGB();
-        case HAL_DATASPACE_DISPLAY_P3:
+        case ui::Dataspace::DISPLAY_P3:
             return SkColorSpace::MakeRGB(
                     SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
         default:
@@ -87,12 +88,26 @@
     }
 }
 
-static uint32_t dataSpaceToInt(android_dataspace d)
+static ui::Dataspace pickBestDataspace(ui::ColorMode colorMode)
+{
+    switch (colorMode) {
+        case ui::ColorMode::SRGB:
+            return ui::Dataspace::V0_SRGB;
+        case ui::ColorMode::DISPLAY_P3:
+        case ui::ColorMode::BT2100_PQ:
+        case ui::ColorMode::BT2100_HLG:
+            return ui::Dataspace::DISPLAY_P3;
+        default:
+            return ui::Dataspace::V0_SRGB;
+    }
+}
+
+static uint32_t dataSpaceToInt(ui::Dataspace d)
 {
     switch (d) {
-        case HAL_DATASPACE_V0_SRGB:
+        case ui::Dataspace::V0_SRGB:
             return COLORSPACE_SRGB;
-        case HAL_DATASPACE_DISPLAY_P3:
+        case ui::Dataspace::DISPLAY_P3:
             return COLORSPACE_DISPLAY_P3;
         default:
             return COLORSPACE_UNKNOWN;
@@ -161,7 +176,6 @@
 
     void* base = NULL;
     uint32_t w, s, h, f;
-    android_dataspace d;
     size_t size = 0;
 
     // Maps orientations from DisplayInfo to ISurfaceComposer
@@ -197,8 +211,15 @@
     uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];
 
     sp<GraphicBuffer> outBuffer;
-    status_t result = ScreenshotClient::capture(display, Rect(), 0 /* reqWidth */,
-            0 /* reqHeight */, false, captureOrientation, &outBuffer);
+    ui::Dataspace reqDataspace =
+        pickBestDataspace(SurfaceComposerClient::getActiveColorMode(display));
+
+    // Due to the fact that we hard code the way we write pixels into screenshot,
+    // we hard code RGBA_8888 here.
+    ui::PixelFormat reqPixelFormat = ui::PixelFormat::RGBA_8888;
+    status_t result = ScreenshotClient::capture(display, reqDataspace, reqPixelFormat, Rect(),
+                                                0 /* reqWidth */, 0 /* reqHeight */, false,
+                                                captureOrientation, &outBuffer);
     if (result != NO_ERROR) {
         close(fd);
         return 1;
@@ -222,12 +243,12 @@
     h = outBuffer->getHeight();
     s = outBuffer->getStride();
     f = outBuffer->getPixelFormat();
-    d = HAL_DATASPACE_UNKNOWN;
     size = s * h * bytesPerPixel(f);
 
     if (png) {
         const SkImageInfo info =
-            SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, dataSpaceToColorSpace(d));
+            SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType,
+                              dataSpaceToColorSpace(reqDataspace));
         SkPixmap pixmap(info, base, s * bytesPerPixel(f));
         struct FDWStream final : public SkWStream {
           size_t fBytesWritten = 0;
@@ -244,7 +265,7 @@
             notifyMediaScanner(fn);
         }
     } else {
-        uint32_t c = dataSpaceToInt(d);
+        uint32_t c = dataSpaceToInt(reqDataspace);
         write(fd, &w, 4);
         write(fd, &h, 4);
         write(fd, &f, 4);
@@ -261,4 +282,4 @@
     }
 
     return 0;
-}
\ No newline at end of file
+}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 2e1e130..4eda3ab 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -166,8 +166,10 @@
     }
     Rect sourceCrop = rectFromObj(env, sourceCropObj);
     sp<GraphicBuffer> buffer;
-    status_t res = ScreenshotClient::capture(displayToken, sourceCrop, width, height,
-            useIdentityTransform, rotation, &buffer);
+    status_t res = ScreenshotClient::capture(displayToken, ui::Dataspace::V0_SRGB,
+                                             ui::PixelFormat::RGBA_8888,
+                                             sourceCrop, width, height,
+                                             useIdentityTransform, rotation, &buffer);
     if (res != NO_ERROR) {
         return NULL;
     }
@@ -195,7 +197,9 @@
     }
 
     sp<GraphicBuffer> buffer;
-    status_t res = ScreenshotClient::captureChildLayers(layerHandle, sourceCrop, frameScale, &buffer);
+    status_t res = ScreenshotClient::captureChildLayers(layerHandle, ui::Dataspace::V0_SRGB,
+                                                        ui::PixelFormat::RGBA_8888, sourceCrop,
+                                                        frameScale, &buffer);
     if (res != NO_ERROR) {
         return NULL;
     }