Merge "SF: Track compositionType across displayId's"
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 7f9668f..81f692d 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -331,6 +331,34 @@
         return result;
     }
 
+    virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayViewport failed to writeInterfaceToken: %d", result);
+            return result;
+        }
+        result = data.writeStrongBinder(display);
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayViewport failed to writeStrongBinder: %d", result);
+            return result;
+        }
+        result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_VIEWPORT, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayViewport failed to transact: %d", result);
+            return result;
+        }
+        result = reply.readInt32();
+        if (result == NO_ERROR) {
+            result = reply.read(*outViewport);
+            if (result != NO_ERROR) {
+                ALOGE("getDisplayViewport failed to read: %d", result);
+                return result;
+            }
+        }
+        return result;
+    }
+
     virtual int getActiveConfig(const sp<IBinder>& display)
     {
         Parcel data, reply;
@@ -747,6 +775,26 @@
             }
             return NO_ERROR;
         }
+        case GET_DISPLAY_VIEWPORT: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            Rect outViewport;
+            sp<IBinder> display = nullptr;
+            status_t result = data.readStrongBinder(&display);
+            if (result != NO_ERROR) {
+                ALOGE("getDisplayViewport failed to readStrongBinder: %d", result);
+                return result;
+            }
+            result = getDisplayViewport(display, &outViewport);
+            result = reply->writeInt32(result);
+            if (result == NO_ERROR) {
+                result = reply->write(outViewport);
+                if (result != NO_ERROR) {
+                    ALOGE("getDisplayViewport failed to write: %d", result);
+                    return result;
+                }
+            }
+            return NO_ERROR;
+        }
         case GET_ACTIVE_CONFIG: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = data.readStrongBinder();
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 17cff54..6518596 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -842,6 +842,10 @@
     return NO_ERROR;
 }
 
+status_t SurfaceComposerClient::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+    return ComposerService::getComposerService()->getDisplayViewport(display, outViewport);
+}
+
 int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) {
     return ComposerService::getComposerService()->getActiveConfig(display);
 }
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 98ec338..b9158f1 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -157,6 +157,9 @@
     virtual status_t getDisplayStats(const sp<IBinder>& display,
             DisplayStatInfo* stats) = 0;
 
+    /* returns display viewport information of the given display */
+    virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) = 0;
+
     /* indicates which of the configurations returned by getDisplayInfo is
      * currently active */
     virtual int getActiveConfig(const sp<IBinder>& display) = 0;
@@ -250,7 +253,8 @@
         ENABLE_VSYNC_INJECTIONS,
         INJECT_VSYNC,
         GET_LAYER_DEBUG_INFO,
-        CREATE_SCOPED_CONNECTION
+        CREATE_SCOPED_CONNECTION,
+        GET_DISPLAY_VIEWPORT
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 4907866..9bd1131 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -79,6 +79,9 @@
     static status_t getDisplayInfo(const sp<IBinder>& display,
             DisplayInfo* info);
 
+    // Get the display viewport for the given display
+    static status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
+
     // Get the index of the current active configuration (relative to the list
     // returned by getDisplayInfo)
     static int getActiveConfig(const sp<IBinder>& display);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3542aba..f22e702 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -581,6 +581,9 @@
             Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
     status_t getDisplayStats(const sp<IBinder>& /*display*/,
             DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
+    status_t getDisplayViewport(const sp<IBinder>& /*display*/, Rect* /*outViewport*/) override {
+        return NO_ERROR;
+    }
     int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; }
     status_t setActiveConfig(const sp<IBinder>& /*display*/, int /*id*/)
             override {
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index b4f7e56..a4f83b7 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -6549,7 +6549,7 @@
 
 bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
     const float scaledX = x * mXScale;
-    const float scaledY = x * mYScale;
+    const float scaledY = y * mYScale;
     return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
             && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
             && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index efaeaa2..ee69b83 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -23,6 +23,7 @@
         "android.hardware.configstore-utils",
         "android.hardware.configstore@1.0",
         "android.hardware.configstore@1.1",
+        "android.hardware.configstore@1.2",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
@@ -175,6 +176,7 @@
         "android.frameworks.displayservice@1.0",
         "android.hardware.configstore-utils",
         "android.hardware.configstore@1.0",
+        "android.hardware.configstore@1.2",
         "android.hardware.graphics.allocator@2.0",
         "libbinder",
         "libcutils",
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 2186594..136d12f 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -114,7 +114,7 @@
       : RenderEngine(featureFlags),
         mVpWidth(0),
         mVpHeight(0),
-        mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
+        mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
 
@@ -132,7 +132,7 @@
 
     // mColorBlindnessCorrection = M;
 
-    if (mPlatformHasWideColor) {
+    if (mUseColorManagement) {
         ColorSpace srgb(ColorSpace::sRGB());
         ColorSpace displayP3(ColorSpace::DisplayP3());
         ColorSpace bt2020(ColorSpace::BT2020());
@@ -322,8 +322,8 @@
     // BT2020 data space, in that case, the output data space is set to be
     // BT2020_HLG or BT2020_PQ respectively. In GPU fall back we need
     // to respect this and convert non-HDR content to HDR format.
-    if (mPlatformHasWideColor) {
-        Description wideColorState = mState;
+    if (mUseColorManagement) {
+        Description managedState = mState;
         Dataspace inputStandard = static_cast<Dataspace>(mDataSpace & Dataspace::STANDARD_MASK);
         Dataspace inputTransfer = static_cast<Dataspace>(mDataSpace & Dataspace::TRANSFER_MASK);
         Dataspace outputStandard = static_cast<Dataspace>(mOutputDataSpace &
@@ -336,26 +336,26 @@
             // The supported input color spaces are standard RGB, Display P3 and BT2020.
             switch (inputStandard) {
                 case Dataspace::STANDARD_DCI_P3:
-                    wideColorState.setInputTransformMatrix(mDisplayP3ToXyz);
+                    managedState.setInputTransformMatrix(mDisplayP3ToXyz);
                     break;
                 case Dataspace::STANDARD_BT2020:
-                    wideColorState.setInputTransformMatrix(mBt2020ToXyz);
+                    managedState.setInputTransformMatrix(mBt2020ToXyz);
                     break;
                 default:
-                    wideColorState.setInputTransformMatrix(mSrgbToXyz);
+                    managedState.setInputTransformMatrix(mSrgbToXyz);
                     break;
             }
 
             // The supported output color spaces are BT2020, Display P3 and standard RGB.
             switch (outputStandard) {
                 case Dataspace::STANDARD_BT2020:
-                    wideColorState.setOutputTransformMatrix(mXyzToBt2020);
+                    managedState.setOutputTransformMatrix(mXyzToBt2020);
                     break;
                 case Dataspace::STANDARD_DCI_P3:
-                    wideColorState.setOutputTransformMatrix(mXyzToDisplayP3);
+                    managedState.setOutputTransformMatrix(mXyzToDisplayP3);
                     break;
                 default:
-                    wideColorState.setOutputTransformMatrix(mXyzToSrgb);
+                    managedState.setOutputTransformMatrix(mXyzToSrgb);
                     break;
             }
         } else if (inputStandard != outputStandard) {
@@ -370,9 +370,9 @@
             // - sRGB
             // - Display P3
             if (outputStandard == Dataspace::STANDARD_BT709) {
-                wideColorState.setOutputTransformMatrix(mDisplayP3ToSrgb);
+                managedState.setOutputTransformMatrix(mDisplayP3ToSrgb);
             } else if (outputStandard == Dataspace::STANDARD_DCI_P3) {
-                wideColorState.setOutputTransformMatrix(mSrgbToDisplayP3);
+                managedState.setOutputTransformMatrix(mSrgbToDisplayP3);
             }
         }
 
@@ -380,44 +380,44 @@
         // - there is a color matrix that is not an identity matrix, or
         // - there is an output transform matrix that is not an identity matrix, or
         // - the input transfer function doesn't match the output transfer function.
-        if (wideColorState.hasColorMatrix() || wideColorState.hasOutputTransformMatrix() ||
+        if (managedState.hasColorMatrix() || managedState.hasOutputTransformMatrix() ||
             inputTransfer != outputTransfer) {
             switch (inputTransfer) {
                 case Dataspace::TRANSFER_ST2084:
-                    wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084);
+                    managedState.setInputTransferFunction(Description::TransferFunction::ST2084);
                     break;
                 case Dataspace::TRANSFER_HLG:
-                    wideColorState.setInputTransferFunction(Description::TransferFunction::HLG);
+                    managedState.setInputTransferFunction(Description::TransferFunction::HLG);
                     break;
                 case Dataspace::TRANSFER_LINEAR:
-                    wideColorState.setInputTransferFunction(Description::TransferFunction::LINEAR);
+                    managedState.setInputTransferFunction(Description::TransferFunction::LINEAR);
                     break;
                 default:
-                    wideColorState.setInputTransferFunction(Description::TransferFunction::SRGB);
+                    managedState.setInputTransferFunction(Description::TransferFunction::SRGB);
                     break;
             }
 
             switch (outputTransfer) {
                 case Dataspace::TRANSFER_ST2084:
-                    wideColorState.setOutputTransferFunction(Description::TransferFunction::ST2084);
+                    managedState.setOutputTransferFunction(Description::TransferFunction::ST2084);
                     break;
                 case Dataspace::TRANSFER_HLG:
-                    wideColorState.setOutputTransferFunction(Description::TransferFunction::HLG);
+                    managedState.setOutputTransferFunction(Description::TransferFunction::HLG);
                     break;
                 default:
-                    wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
+                    managedState.setOutputTransferFunction(Description::TransferFunction::SRGB);
                     break;
             }
         }
 
-        ProgramCache::getInstance().useProgram(wideColorState);
+        ProgramCache::getInstance().useProgram(managedState);
 
         glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
 
         if (outputDebugPPMs) {
-            static uint64_t wideColorFrameCount = 0;
+            static uint64_t managedColorFrameCount = 0;
             std::ostringstream out;
-            out << "/data/texture_out" << wideColorFrameCount++;
+            out << "/data/texture_out" << managedColorFrameCount++;
             writePPM(out.str().c_str(), mVpWidth, mVpHeight);
         }
     } else {
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index f682225..d8cb73b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -94,8 +94,9 @@
     // Current output dataspace of the render engine
     ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN;
 
-    // Currently only supporting sRGB, BT2020 and DisplayP3 color spaces
-    const bool mPlatformHasWideColor = false;
+    // Whether device supports color management, currently color management
+    // supports sRGB, DisplayP3 color spaces.
+    const bool mUseColorManagement = false;
     mat4 mSrgbToDisplayP3;
     mat4 mDisplayP3ToSrgb;
     mat3 mSrgbToXyz;
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 9dc6858..a1d0561 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -82,7 +82,7 @@
 
 ProgramCache::~ProgramCache() {}
 
-void ProgramCache::primeCache(bool hasWideColor) {
+void ProgramCache::primeCache(bool useColorManagement) {
     uint32_t shaderCount = 0;
     uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | Key::ALPHA_MASK | Key::TEXTURE_MASK;
     // Prime the cache for all combinations of the above masks,
@@ -105,7 +105,7 @@
     }
 
     // Prime for sRGB->P3 conversion
-    if (hasWideColor) {
+    if (useColorManagement) {
         Key shaderKey;
         shaderKey.set(Key::BLEND_MASK | Key::TEXTURE_MASK | Key::OUTPUT_TRANSFORM_MATRIX_MASK |
                               Key::INPUT_TF_MASK | Key::OUTPUT_TF_MASK,
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 983e7ba..424633e 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -161,7 +161,7 @@
     ~ProgramCache();
 
     // Generate shaders to populate the cache
-    void primeCache(bool hasWideColor);
+    void primeCache(bool useColorManagement);
 
     // useProgram lookup a suitable program in the cache or generates one
     // if none can be found.
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 39f7e30..e5dbe2f 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -596,7 +596,7 @@
 }
 
 void RenderEngine::primeCache() const {
-    ProgramCache::getInstance().primeCache(mFeatureFlags & WIDE_COLOR_SUPPORT);
+    ProgramCache::getInstance().primeCache(mFeatureFlags & USE_COLOR_MANAGEMENT);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 2ed2cc7..6213784 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -56,7 +56,7 @@
 class RenderEngine {
 public:
     enum FeatureFlag {
-        WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
+        USE_COLOR_MANAGEMENT = 1 << 0, // Device manages color
     };
 
     virtual ~RenderEngine() = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8cee8d7..1705a3f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -93,6 +93,7 @@
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
 #include <android/hardware/configstore/1.1/types.h>
 #include <configstore/Utils.h>
 
@@ -176,6 +177,7 @@
 int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
 // TODO(courtneygo): Rename hasWideColorDisplay to clarify its actual meaning.
 bool SurfaceFlinger::hasWideColorDisplay;
+bool SurfaceFlinger::useColorManagement;
 
 
 std::string getHwcServiceName() {
@@ -302,6 +304,8 @@
 
     hasWideColorDisplay =
             getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+    useColorManagement =
+            getBool<V1_2::ISurfaceFlingerConfigs, &V1_2::ISurfaceFlingerConfigs::useColorManagement>(false);
 
     V1_1::DisplayOrientation primaryDisplayOrientation =
         getDisplayOrientation< V1_1::ISurfaceFlingerConfigs, &V1_1::ISurfaceFlingerConfigs::primaryDisplayOrientation>(
@@ -597,11 +601,10 @@
     mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
 
     // Get a RenderEngine for the given display / config (can't fail)
+    int32_t renderEngineFeature = 0;
+    renderEngineFeature |= (useColorManagement ? RE::RenderEngine::USE_COLOR_MANAGEMENT : 0);
     getBE().mRenderEngine =
-            RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
-                                           hasWideColorDisplay
-                                                   ? RE::RenderEngine::WIDE_COLOR_SUPPORT
-                                                   : 0);
+            RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, renderEngineFeature);
     LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
 
     LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
@@ -874,6 +877,21 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+    if (outViewport == nullptr || display.get() == nullptr) {
+        return BAD_VALUE;
+    }
+
+    sp<const DisplayDevice> device(getDisplayDevice(display));
+    if (device == nullptr) {
+        return BAD_VALUE;
+    }
+
+    *outViewport = device->getViewport();
+
+    return NO_ERROR;
+}
+
 int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
     const auto display = getDisplayDevice(displayToken);
     if (!display) {
@@ -1544,7 +1562,7 @@
             layer->setPerFrameData(display);
         }
 
-        if (hasWideColorDisplay) {
+        if (useColorManagement) {
             ColorMode  colorMode;
             Dataspace dataSpace;
             RenderIntent renderIntent;
@@ -1983,8 +2001,8 @@
     //   emit any black frames until a layer is added to the layer stack.
     bool mustRecompose = dirty && !(empty && wasEmpty);
 
-    ALOGV_IF(displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
-            "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
+    ALOGV_IF(display->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
+            "id[%d]: %s composition (%sdirty %sempty %swasEmpty)", display->getId(),
             mustRecompose ? "doing" : "skipping",
             dirty ? "+" : "-",
             empty ? "+" : "-",
@@ -2204,7 +2222,7 @@
     HdrCapabilities hdrCapabilities;
     int32_t supportedPerFrameMetadata = 0;
 
-    if (hasWideColorDisplay && displayId >= 0) {
+    if (useColorManagement && displayId >= 0) {
         std::vector<ColorMode> modes = getHwComposer().getColorModes(displayId);
         for (ColorMode colorMode : modes) {
             if (isWideColorMode(colorMode)) {
@@ -2910,22 +2928,17 @@
             }
         }
 
-        if (!display->isPrimary()) {
-            // just to be on the safe side, we don't set the
-            // scissor on the main display. It should never be needed
-            // anyways (though in theory it could since the API allows it).
-            const Rect& bounds = display->getBounds();
-            const Rect& scissor = display->getScissor();
-            if (scissor != bounds) {
-                // scissor doesn't match the screen's dimensions, so we
-                // need to clear everything outside of it and enable
-                // the GL scissor so we don't draw anything where we shouldn't
+        const Rect& bounds = display->getBounds();
+        const Rect& scissor = display->getScissor();
+        if (scissor != bounds) {
+            // scissor doesn't match the screen's dimensions, so we
+            // need to clear everything outside of it and enable
+            // the GL scissor so we don't draw anything where we shouldn't
 
-                // enable scissor for this frame
-                const uint32_t height = display->getHeight();
-                getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
-                        scissor.getWidth(), scissor.getHeight());
-            }
+            // enable scissor for this frame
+            const uint32_t height = display->getHeight();
+            getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
+                                              scissor.getWidth(), scissor.getHeight());
         }
     }
 
@@ -4142,7 +4155,8 @@
 }
 
 void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
-    result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
+    result.appendFormat("Device has wide color display: %d\n", hasWideColorDisplay);
+    result.appendFormat("Device uses color management: %d\n", useColorManagement);
     result.appendFormat("DisplayColorSetting: %s\n",
             decodeDisplayColorSetting(mDisplayColorSetting).c_str());
 
@@ -4490,6 +4504,7 @@
         case GET_DISPLAY_COLOR_MODES:
         case GET_DISPLAY_CONFIGS:
         case GET_DISPLAY_STATS:
+        case GET_DISPLAY_VIEWPORT:
         case GET_SUPPORTED_FRAME_TIMESTAMPS:
         // Calling setTransactionState is safe, because you need to have been
         // granted a reference to Client* and Handle* to do anything with it.
@@ -4716,7 +4731,9 @@
                 repaintEverything();
                 return NO_ERROR;
             }
-            case 1024: { // Is wide color gamut rendering/color management supported?
+            // TODO(b/111505327): Find out whether the usage of 1024 can switch to 1030,
+            // deprecate 1024 if they can.
+            case 1024: { // Does device have wide color gamut display?
                 reply->writeBool(hasWideColorDisplay);
                 return NO_ERROR;
             }
@@ -4748,7 +4765,7 @@
                 DisplayColorSetting setting = static_cast<DisplayColorSetting>(data.readInt32());
                 switch (setting) {
                     case DisplayColorSetting::MANAGED:
-                        reply->writeBool(hasWideColorDisplay);
+                        reply->writeBool(useColorManagement);
                         break;
                     case DisplayColorSetting::UNMANAGED:
                         reply->writeBool(true);
@@ -4796,6 +4813,11 @@
                 ATRACE_INT("PeriodDivisor", divisor);
                 return NO_ERROR;
             }
+            // Is device color managed?
+            case 1030: {
+                reply->writeBool(useColorManagement);
+                return NO_ERROR;
+            }
         }
     }
     return err;
@@ -4836,8 +4858,8 @@
         sourceCrop.set(dispScissor);
         // adb shell screencap will default reqWidth and reqHeight to zeros.
         if (reqWidth == 0 || reqHeight == 0) {
-            reqWidth = uint32_t(dispScissor.width());
-            reqHeight = uint32_t(dispScissor.height());
+            reqWidth = uint32_t(display->getViewport().width());
+            reqHeight = uint32_t(display->getViewport().height());
         }
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index bdbd6ab..3910699 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -283,13 +283,13 @@
     // FramebufferSurface
     static int64_t maxFrameBufferAcquiredBuffers;
 
-    // Indicate if platform supports color management on its
-    // wide-color display. This is typically found on devices
-    // with wide gamut (e.g. Display-P3) display.
-    // This also allows devices with wide-color displays that don't
-    // want to support color management to disable color management.
+    // Indicate if a device has wide color gamut display. This is typically
+    // found on devices with wide color gamut (e.g. Display-P3) display.
     static bool hasWideColorDisplay;
 
+    // Indicate if device wants color management on its display.
+    static bool useColorManagement;
+
     static char const* getServiceName() ANDROID_API {
         return "SurfaceFlinger";
     }
@@ -434,6 +434,7 @@
     virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
                                    const Rect& sourceCrop, float frameScale, bool childrenOnly);
     virtual status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
+    virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
     virtual status_t getDisplayConfigs(const sp<IBinder>& displayToken,
                                        Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& displayToken);
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index e34772f..7f882da 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -80,12 +80,12 @@
   optional int32 hwc_composition_type = 35;
   // If it's a buffer layer, indicate if the content is protected
   optional bool is_protected = 36;
-  // If active_buffer is not null, record its transform
-  optional TransformProto buffer_transform = 37;
   // Current frame number being rendered.
-  optional uint64 curr_frame = 38;
+  optional uint64 curr_frame = 37;
   // A list of barriers that the layer is waiting to update state.
-  repeated BarrierLayerProto barrier_layer = 39;
+  repeated BarrierLayerProto barrier_layer = 38;
+  // If active_buffer is not null, record its transform.
+  optional TransformProto buffer_transform = 39;
 }
 
 message PositionProto {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index b4aec36..1f57b8e 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -137,6 +137,7 @@
 
     // Default to no wide color display support configured
     mFlinger.mutableHasWideColorDisplay() = false;
+    mFlinger.mutableUseColorManagement() = false;
     mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::UNMANAGED;
 
     // Default to using HWC virtual displays
@@ -455,6 +456,7 @@
 
     static void injectConfigChange(DisplayTransactionTest* test) {
         test->mFlinger.mutableHasWideColorDisplay() = false;
+        test->mFlinger.mutableUseColorManagement() = false;
         test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::UNMANAGED;
     }
 
@@ -473,6 +475,7 @@
     static constexpr bool WIDE_COLOR_SUPPORTED = true;
 
     static void injectConfigChange(DisplayTransactionTest* test) {
+        test->mFlinger.mutableUseColorManagement() = true;
         test->mFlinger.mutableHasWideColorDisplay() = true;
         test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::UNMANAGED;
     }
@@ -501,6 +504,7 @@
     static constexpr bool WIDE_COLOR_SUPPORTED = false;
 
     static void injectConfigChange(DisplayTransactionTest* test) {
+        test->mFlinger.mutableUseColorManagement() = true;
         test->mFlinger.mutableHasWideColorDisplay() = true;
     }
 
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 9df4264..d8e7581 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -113,6 +113,7 @@
      */
 
     auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; }
+    auto& mutableUseColorManagement() { return SurfaceFlinger::useColorManagement; }
 
     auto& mutableDisplayTokens() { return mFlinger->mDisplayTokens; }
     auto& mutableCurrentState() { return mFlinger->mCurrentState; }