Merge "Add ability to use float densities."
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/libs/ui/Android.bp b/libs/ui/Android.bp
index d25ad1a..e3ef2a9 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -65,6 +65,7 @@
         "PixelFormat.cpp",
         "Rect.cpp",
         "Region.cpp",
+        "Transform.cpp",
         "UiConfig.cpp",
     ],
 
diff --git a/services/surfaceflinger/Transform.cpp b/libs/ui/Transform.cpp
similarity index 82%
rename from services/surfaceflinger/Transform.cpp
rename to libs/ui/Transform.cpp
index bc9e5cd..8e949ec 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/libs/ui/Transform.cpp
@@ -17,16 +17,12 @@
 #include <math.h>
 
 #include <cutils/compiler.h>
-#include <utils/String8.h>
 #include <ui/Region.h>
-
-#include "Transform.h"
-
-// ---------------------------------------------------------------------------
+#include <ui/Transform.h>
+#include <utils/String8.h>
 
 namespace android {
-
-// ---------------------------------------------------------------------------
+namespace ui {
 
 Transform::Transform() {
     reset();
@@ -40,8 +36,7 @@
     set(orientation, 0, 0);
 }
 
-Transform::~Transform() {
-}
+Transform::~Transform() = default;
 
 static const float EPSILON = 0.0f;
 
@@ -66,7 +61,7 @@
     const mat33& A(mMatrix);
     const mat33& B(rhs.mMatrix);
           mat33& D(r.mMatrix);
-    for (int i=0 ; i<3 ; i++) {
+    for (size_t i = 0; i < 3; i++) {
         const float v0 = A[0][i];
         const float v1 = A[1][i];
         const float v2 = A[2][i];
@@ -82,6 +77,12 @@
     return r;
 }
 
+Transform& Transform::operator=(const Transform& other) {
+    mMatrix = other.mMatrix;
+    mType = other.mType;
+    return *this;
+}
+
 const vec3& Transform::operator [] (size_t i) const {
     return mMatrix[i];
 }
@@ -96,10 +97,10 @@
 
 void Transform::reset() {
     mType = IDENTITY;
-    for(int i=0 ; i<3 ; i++) {
+    for(size_t i = 0; i < 3; i++) {
         vec3& v(mMatrix[i]);
-        for (int j=0 ; j<3 ; j++)
-            v[j] = ((i==j) ? 1.0f : 0.0f);
+        for (size_t j = 0; j < 3; j++)
+            v[j] = ((i == j) ? 1.0f : 0.0f);
     }
 }
 
@@ -209,15 +210,15 @@
     rb = transform(rb);
 
     if (roundOutwards) {
-        r.left   = floorf(std::min({lt[0], rt[0], lb[0], rb[0]}));
-        r.top    = floorf(std::min({lt[1], rt[1], lb[1], rb[1]}));
-        r.right  = ceilf(std::max({lt[0], rt[0], lb[0], rb[0]}));
-        r.bottom = ceilf(std::max({lt[1], rt[1], lb[1], rb[1]}));
+        r.left   = static_cast<int32_t>(floorf(std::min({lt[0], rt[0], lb[0], rb[0]})));
+        r.top    = static_cast<int32_t>(floorf(std::min({lt[1], rt[1], lb[1], rb[1]})));
+        r.right  = static_cast<int32_t>(ceilf(std::max({lt[0], rt[0], lb[0], rb[0]})));
+        r.bottom = static_cast<int32_t>(ceilf(std::max({lt[1], rt[1], lb[1], rb[1]})));
     } else {
-        r.left   = floorf(std::min({lt[0], rt[0], lb[0], rb[0]}) + 0.5f);
-        r.top    = floorf(std::min({lt[1], rt[1], lb[1], rb[1]}) + 0.5f);
-        r.right  = floorf(std::max({lt[0], rt[0], lb[0], rb[0]}) + 0.5f);
-        r.bottom = floorf(std::max({lt[1], rt[1], lb[1], rb[1]}) + 0.5f);
+        r.left   = static_cast<int32_t>(floorf(std::min({lt[0], rt[0], lb[0], rb[0]}) + 0.5f));
+        r.top    = static_cast<int32_t>(floorf(std::min({lt[1], rt[1], lb[1], rb[1]}) + 0.5f));
+        r.right  = static_cast<int32_t>(floorf(std::max({lt[0], rt[0], lb[0], rb[0]}) + 0.5f));
+        r.bottom = static_cast<int32_t>(floorf(std::max({lt[1], rt[1], lb[1], rb[1]}) + 0.5f));
     }
 
     return r;
@@ -258,8 +259,8 @@
             out.set(transform(reg.bounds()));
         }
     } else {
-        int xpos = floorf(tx() + 0.5f);
-        int ypos = floorf(ty() + 0.5f);
+        int xpos = static_cast<int>(floorf(tx() + 0.5f));
+        int ypos = static_cast<int>(floorf(ty() + 0.5f));
         out = reg.translate(xpos, ypos);
     }
     return out;
@@ -342,7 +343,7 @@
         const float x = M[2][0];
         const float y = M[2][1];
 
-        const float idet = 1.0 / (a*d - b*c);
+        const float idet = 1.0f / (a*d - b*c);
         result.mMatrix[0][0] =  d*idet;
         result.mMatrix[0][1] = -c*idet;
         result.mMatrix[1][0] = -b*idet;
@@ -403,28 +404,13 @@
         type.append("TRANSLATE ");
 
     ALOGD("%s 0x%08x (%s, %s)", name, mType, flags.string(), type.string());
-    ALOGD("%.4f  %.4f  %.4f", m[0][0], m[1][0], m[2][0]);
-    ALOGD("%.4f  %.4f  %.4f", m[0][1], m[1][1], m[2][1]);
-    ALOGD("%.4f  %.4f  %.4f", m[0][2], m[1][2], m[2][2]);
+    ALOGD("%.4f  %.4f  %.4f", static_cast<double>(m[0][0]), static_cast<double>(m[1][0]),
+          static_cast<double>(m[2][0]));
+    ALOGD("%.4f  %.4f  %.4f", static_cast<double>(m[0][1]), static_cast<double>(m[1][1]),
+          static_cast<double>(m[2][1]));
+    ALOGD("%.4f  %.4f  %.4f", static_cast<double>(m[0][2]), static_cast<double>(m[1][2]),
+          static_cast<double>(m[2][2]));
 }
 
-Transform::orientation_flags Transform::fromRotation(ISurfaceComposer::Rotation rotation) {
-    // Convert to surfaceflinger's internal rotation type.
-    switch (rotation) {
-        case ISurfaceComposer::eRotateNone:
-            return Transform::ROT_0;
-        case ISurfaceComposer::eRotate90:
-            return Transform::ROT_90;
-        case ISurfaceComposer::eRotate180:
-            return Transform::ROT_180;
-        case ISurfaceComposer::eRotate270:
-            return Transform::ROT_270;
-        default:
-            ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
-            return Transform::ROT_0;
-    }
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
+}  // namespace ui
+}  // namespace android
diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h
new file mode 100644
index 0000000..42dca75
--- /dev/null
+++ b/libs/ui/include/ui/Transform.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#ifndef ANDROID_TRANSFORM_H
+#define ANDROID_TRANSFORM_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <hardware/hardware.h>
+#include <math/vec2.h>
+#include <math/vec3.h>
+#include <ui/Point.h>
+#include <ui/Rect.h>
+
+namespace android {
+
+class Region;
+
+namespace ui {
+
+class Transform {
+public:
+    Transform();
+    Transform(const Transform&  other);
+    explicit Transform(uint32_t orientation);
+    ~Transform();
+
+    enum orientation_flags {
+        ROT_0   = 0x00000000,
+        FLIP_H  = HAL_TRANSFORM_FLIP_H,
+        FLIP_V  = HAL_TRANSFORM_FLIP_V,
+        ROT_90  = HAL_TRANSFORM_ROT_90,
+        ROT_180 = FLIP_H|FLIP_V,
+        ROT_270 = ROT_180|ROT_90,
+        ROT_INVALID = 0x80
+    };
+
+    enum type_mask : uint32_t {
+        IDENTITY            = 0,
+        TRANSLATE           = 0x1,
+        ROTATE              = 0x2,
+        SCALE               = 0x4,
+        UNKNOWN             = 0x8
+    };
+
+    // query the transform
+    bool        preserveRects() const;
+    uint32_t    getType() const;
+    uint32_t    getOrientation() const;
+
+    const vec3& operator [] (size_t i) const;  // returns column i
+    float   tx() const;
+    float   ty() const;
+
+    // modify the transform
+    void        reset();
+    void        set(float tx, float ty);
+    void        set(float a, float b, float c, float d);
+    status_t    set(uint32_t flags, float w, float h);
+
+    // transform data
+    Rect    makeBounds(int w, int h) const;
+    vec2    transform(int x, int y) const;
+    Region  transform(const Region& reg) const;
+    Rect    transform(const Rect& bounds,
+                      bool roundOutwards = false) const;
+    FloatRect transform(const FloatRect& bounds) const;
+    Transform& operator = (const Transform& other);
+    Transform operator * (const Transform& rhs) const;
+    // assumes the last row is < 0 , 0 , 1 >
+    vec2 transform(const vec2& v) const;
+    vec3 transform(const vec3& v) const;
+
+    Transform inverse() const;
+
+    // for debugging
+    void dump(const char* name) const;
+
+private:
+    struct mat33 {
+        vec3 v[3];
+        inline const vec3& operator [] (size_t i) const { return v[i]; }
+        inline vec3& operator [] (size_t i) { return v[i]; }
+    };
+
+    enum { UNKNOWN_TYPE = 0x80000000 };
+
+    uint32_t type() const;
+    static bool absIsOne(float f);
+    static bool isZero(float f);
+
+    mat33               mMatrix;
+    mutable uint32_t    mType;
+};
+
+}  // namespace ui
+}  // namespace android
+
+#endif /* ANDROID_TRANSFORM_H */
diff --git a/libs/vr/CleanSpec.mk b/libs/vr/CleanSpec.mk
new file mode 100644
index 0000000..a17c9b2
--- /dev/null
+++ b/libs/vr/CleanSpec.mk
@@ -0,0 +1,52 @@
+# Copyright (C) 2012 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libdvr.so" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvr_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvr_intermediates)
diff --git a/libs/vr/libbufferhubqueue/benchmarks/Android.bp b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
index 5089b87..ef1eed6 100644
--- a/libs/vr/libbufferhubqueue/benchmarks/Android.bp
+++ b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
@@ -5,7 +5,7 @@
         "libbase",
         "libbinder",
         "libcutils",
-        "libdvr",
+        "libdvr.google",
         "libgui",
         "liblog",
         "libhardware",
diff --git a/libs/vr/libbufferhubqueue/benchmarks/buffer_transport_benchmark.cpp b/libs/vr/libbufferhubqueue/benchmarks/buffer_transport_benchmark.cpp
index 4ca8671..b2b4d7a 100644
--- a/libs/vr/libbufferhubqueue/benchmarks/buffer_transport_benchmark.cpp
+++ b/libs/vr/libbufferhubqueue/benchmarks/buffer_transport_benchmark.cpp
@@ -206,7 +206,7 @@
 class DvrApi {
  public:
   DvrApi() {
-    handle_ = dlopen("libdvr.so", RTLD_NOW | RTLD_LOCAL);
+    handle_ = dlopen("libdvr.google.so", RTLD_NOW | RTLD_LOCAL);
     CHECK(handle_);
 
     auto dvr_get_api =
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index 3829951..81a9b2d 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -73,7 +73,7 @@
 ]
 
 cc_library_shared {
-    name: "libdvr",
+    name: "libdvr.google",
     owner: "google",
     cflags: cflags,
     header_libs: ["libdvr_headers"],
@@ -88,7 +88,7 @@
 // restricting function access in the shared lib makes it inconvenient to use in
 // test code.
 cc_library_static {
-    name: "libdvr_static",
+    name: "libdvr_static.google",
     owner: "google",
     cflags: cflags,
     header_libs: ["libdvr_headers"],
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index b23a0fa..3260447 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -21,7 +21,7 @@
 
     header_libs: ["libdvr_headers"],
     static_libs: [
-        "libdvr_static",
+        "libdvr_static.google",
         "libchrome",
         "libdvrcommon",
         "libdisplay",
diff --git a/libs/vr/libdvr/tests/dvr_api_test.h b/libs/vr/libdvr/tests/dvr_api_test.h
index d8359e7..5d2ec28 100644
--- a/libs/vr/libdvr/tests/dvr_api_test.h
+++ b/libs/vr/libdvr/tests/dvr_api_test.h
@@ -14,7 +14,7 @@
     // workaround for an Android NDK bug. See more detail:
     // https://github.com/android-ndk/ndk/issues/360
     flags |= RTLD_NODELETE;
-    platform_handle_ = dlopen("libdvr.so", flags);
+    platform_handle_ = dlopen("libdvr.google.so", flags);
     ASSERT_NE(nullptr, platform_handle_) << "Dvr shared library missing.";
 
     auto dvr_get_api = reinterpret_cast<decltype(&dvrGetApi)>(
diff --git a/libs/vr/public.libraries-google.txt b/libs/vr/public.libraries-google.txt
new file mode 100644
index 0000000..8271b94
--- /dev/null
+++ b/libs/vr/public.libraries-google.txt
@@ -0,0 +1 @@
+libdvr.google.so
\ No newline at end of file
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index beda75a..a4f83b7 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -3089,6 +3089,7 @@
         InputMapper(device),
         mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
         mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
+        mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0),
         mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
 }
 
@@ -3596,6 +3597,11 @@
                 break;
             }
 
+            mPhysicalWidth = naturalPhysicalWidth;
+            mPhysicalHeight = naturalPhysicalHeight;
+            mPhysicalLeft = naturalPhysicalLeft;
+            mPhysicalTop = naturalPhysicalTop;
+
             mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
             mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
             mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
@@ -3604,6 +3610,11 @@
             mSurfaceOrientation = mParameters.orientationAware ?
                     mViewport.orientation : DISPLAY_ORIENTATION_0;
         } else {
+            mPhysicalWidth = rawWidth;
+            mPhysicalHeight = rawHeight;
+            mPhysicalLeft = 0;
+            mPhysicalTop = 0;
+
             mSurfaceWidth = rawWidth;
             mSurfaceHeight = rawHeight;
             mSurfaceLeft = 0;
@@ -3914,6 +3925,10 @@
     dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
     dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
     dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
+    dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
+    dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
+    dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
+    dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
     dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
 }
 
@@ -5120,10 +5135,10 @@
             }
             break;
         case DISPLAY_ORIENTATION_180:
-            x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
+            x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
             y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
-            left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
-            right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
+            left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
+            right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
             bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
             top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
             orientation -= M_PI;
@@ -5132,10 +5147,10 @@
             }
             break;
         case DISPLAY_ORIENTATION_270:
-            x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
+            x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
             y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
-            left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
-            right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
+            left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
+            right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
             bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
             top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
             orientation += M_PI_2;
@@ -6533,8 +6548,12 @@
 }
 
 bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
+    const float scaledX = x * mXScale;
+    const float scaledY = y * mYScale;
     return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
-            && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
+            && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
+            && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
+            && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
 }
 
 const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 89290a8..af26b4f 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1521,13 +1521,21 @@
     // in the natural orientation.
     // The surface origin specifies how the surface coordinates should be translated
     // to align with the logical display coordinate space.
-    // The orientation may be different from the viewport orientation as it specifies
-    // the rotation of the surface coordinates required to produce the viewport's
-    // requested orientation, so it will depend on whether the device is orientation aware.
     int32_t mSurfaceWidth;
     int32_t mSurfaceHeight;
     int32_t mSurfaceLeft;
     int32_t mSurfaceTop;
+
+    // Similar to the surface coordinates, but in the raw display coordinate space rather than in
+    // the logical coordinate space.
+    int32_t mPhysicalWidth;
+    int32_t mPhysicalHeight;
+    int32_t mPhysicalLeft;
+    int32_t mPhysicalTop;
+
+    // The orientation may be different from the viewport orientation as it specifies
+    // the rotation of the surface coordinates required to produce the viewport's
+    // requested orientation, so it will depend on whether the device is orientation aware.
     int32_t mSurfaceOrientation;
 
     // Translation and scaling factors, orientation-independent.
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index fa0141f..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",
@@ -137,7 +138,6 @@
         "SurfaceInterceptor.cpp",
         "SurfaceTracing.cpp",
         "TimeStats/TimeStats.cpp",
-        "Transform.cpp",
     ],
 }
 
@@ -176,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/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 2c91da0..f48aa47 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -258,7 +258,7 @@
 void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& display) {
     // Apply this display's projection's viewport to the visible region
     // before giving it to the HWC HAL.
-    const Transform& tr = display->getTransform();
+    const ui::Transform& tr = display->getTransform();
     const auto& viewport = display->getViewport();
     Region visible = tr.transform(visibleRegion.intersect(viewport));
     const auto displayId = display->getId();
@@ -275,6 +275,7 @@
               to_string(error).c_str(), static_cast<int32_t>(error));
         visible.dump(LOG_TAG);
     }
+    getBE().compositionInfo.hwc.visibleRegion = visible;
 
     error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
     if (error != HWC2::Error::None) {
@@ -282,6 +283,7 @@
               to_string(error).c_str(), static_cast<int32_t>(error));
         surfaceDamageRegion.dump(LOG_TAG);
     }
+    getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion;
 
     // Sideband layers
     if (getBE().compositionInfo.hwc.sidebandStream.get()) {
@@ -293,6 +295,7 @@
                   getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(),
                   static_cast<int32_t>(error));
         }
+        getBE().compositionInfo.compositionType = HWC2::Composition::Sideband;
         return;
     }
 
@@ -318,6 +321,9 @@
         ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(),
               to_string(error).c_str(), static_cast<int32_t>(error));
     }
+    getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
+    getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata();
+    getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata();
 
     setHwcLayerBuffer(display);
 }
@@ -638,7 +644,7 @@
      */
     const Rect bounds{computeBounds()}; // Rounds from FloatRect
 
-    Transform t = getTransform();
+    ui::Transform t = getTransform();
     Rect win = bounds;
     Rect finalCrop = getFinalCrop(s);
     if (!finalCrop.isEmpty()) {
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 13f4e83..0b641b7 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -27,7 +27,6 @@
 #include "RenderEngine/Mesh.h"
 #include "RenderEngine/Texture.h"
 #include "SurfaceFlinger.h"
-#include "Transform.h"
 
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/LayerState.h>
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 6dd29ba..dc908d2 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -353,6 +353,9 @@
               getBE().compositionInfo.mBuffer->handle, to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
+    getBE().compositionInfo.mBufferSlot = mActiveBufferSlot;
+    getBE().compositionInfo.mBuffer = mActiveBuffer;
+    getBE().compositionInfo.hwc.fence = acquireFence;
 }
 
 // -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 276e0e1..369ad89 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -213,7 +213,7 @@
 
 bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix,
                                  bool allowNonRectPreservingTransforms) {
-    Transform t;
+    ui::Transform t;
     t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
 
     if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
@@ -399,13 +399,13 @@
     uint32_t bufferWidth = s.buffer->width;
     uint32_t bufferHeight = s.buffer->height;
 
-    if (s.transform & Transform::ROT_90) {
+    if (s.transform & ui::Transform::ROT_90) {
         std::swap(bufferWidth, bufferHeight);
     }
 
     if (s.transformToDisplayInverse) {
         uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
-        if (invTransform & Transform::ROT_90) {
+        if (invTransform & ui::Transform::ROT_90) {
             std::swap(bufferWidth, bufferHeight);
         }
     }
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 4d7396e..e492375 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -52,7 +52,7 @@
 
     uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; }
     uint32_t getActiveHeight(const Layer::State& s) const override { return s.active.h; }
-    Transform getActiveTransform(const Layer::State& s) const override {
+    ui::Transform getActiveTransform(const Layer::State& s) const override {
         return s.active.transform;
     }
     Region getActiveTransparentRegion(const Layer::State& s) const override {
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index bac46a3..f8bb94e 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -72,7 +72,7 @@
 }
 
 void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& display) {
-    const Transform& tr = display->getTransform();
+    const ui::Transform& tr = display->getTransform();
     const auto& viewport = display->getViewport();
     Region visible = tr.transform(visibleRegion.intersect(viewport));
     const auto displayId = display->getId();
@@ -89,6 +89,7 @@
               to_string(error).c_str(), static_cast<int32_t>(error));
         visible.dump(LOG_TAG);
     }
+    getBE().compositionInfo.hwc.visibleRegion = visible;
 
     setCompositionType(displayId, HWC2::Composition::SolidColor);
 
@@ -97,6 +98,7 @@
         ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentDataSpace,
               to_string(error).c_str(), static_cast<int32_t>(error));
     }
+    getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
 
     half4 color = getColor();
     error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
@@ -106,6 +108,9 @@
         ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
+    getBE().compositionInfo.hwc.color = { static_cast<uint8_t>(std::round(255.0f * color.r)),
+                                      static_cast<uint8_t>(std::round(255.0f * color.g)),
+                                      static_cast<uint8_t>(std::round(255.0f * color.b)), 255 };
 
     // Clear out the transform, because it doesn't make sense absent a source buffer
     error = hwcLayer->setTransform(HWC2::Transform::None);
@@ -113,6 +118,7 @@
         ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
+    getBE().compositionInfo.hwc.transform = HWC2::Transform::None;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 54c0dbe..776b84a 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -389,7 +389,7 @@
     size_t h = mDisplayHeight;
     Rect sourceCrop(0, 0, w, h);
     mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h,
-        false, Transform::ROT_0);
+        false, ui::Transform::ROT_0);
 }
 
 const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
@@ -419,7 +419,7 @@
     if (repaintEverything) {
         dirty.set(getBounds());
     } else {
-        const Transform& planeTransform(mGlobalTransform);
+        const ui::Transform& planeTransform(mGlobalTransform);
         dirty = planeTransform.transform(this->dirtyRegion);
         dirty.andSelf(getBounds());
     }
@@ -498,37 +498,37 @@
     uint32_t transform = 0;
     switch (mOrientation) {
         case DisplayState::eOrientationDefault:
-            transform = Transform::ROT_0;
+            transform = ui::Transform::ROT_0;
             break;
         case DisplayState::eOrientation90:
-            transform = Transform::ROT_90;
+            transform = ui::Transform::ROT_90;
             break;
         case DisplayState::eOrientation180:
-            transform = Transform::ROT_180;
+            transform = ui::Transform::ROT_180;
             break;
         case DisplayState::eOrientation270:
-            transform = Transform::ROT_270;
+            transform = ui::Transform::ROT_270;
             break;
     }
     return transform;
 }
 
 status_t DisplayDevice::orientationToTransfrom(
-        int orientation, int w, int h, Transform* tr)
+        int orientation, int w, int h, ui::Transform* tr)
 {
     uint32_t flags = 0;
     switch (orientation) {
     case DisplayState::eOrientationDefault:
-        flags = Transform::ROT_0;
+        flags = ui::Transform::ROT_0;
         break;
     case DisplayState::eOrientation90:
-        flags = Transform::ROT_90;
+        flags = ui::Transform::ROT_90;
         break;
     case DisplayState::eOrientation180:
-        flags = Transform::ROT_180;
+        flags = ui::Transform::ROT_180;
         break;
     case DisplayState::eOrientation270:
-        flags = Transform::ROT_270;
+        flags = ui::Transform::ROT_270;
         break;
     default:
         return BAD_VALUE;
@@ -563,7 +563,7 @@
     const int w = mDisplayWidth;
     const int h = mDisplayHeight;
 
-    Transform R;
+    ui::Transform R;
     DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
 
     if (!frame.isValid()) {
@@ -578,7 +578,7 @@
         // it's also invalid to have an empty viewport, so we handle that
         // case in the same way.
         viewport = Rect(w, h);
-        if (R.getOrientation() & Transform::ROT_90) {
+        if (R.getOrientation() & ui::Transform::ROT_90) {
             // viewport is always specified in the logical orientation
             // of the display (ie: post-rotation).
             std::swap(viewport.right, viewport.bottom);
@@ -587,7 +587,7 @@
 
     dirtyRegion.set(getBounds());
 
-    Transform TL, TP, S;
+    ui::Transform TL, TP, S;
     float src_width  = viewport.width();
     float src_height = viewport.height();
     float dst_width  = frame.width();
@@ -621,7 +621,7 @@
 
     const uint8_t type = mGlobalTransform.getType();
     mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
-            (type >= Transform::SCALE));
+            (type >= ui::Transform::SCALE));
 
     mScissor = mGlobalTransform.transform(viewport);
     if (mScissor.isEmpty()) {
@@ -633,16 +633,16 @@
         uint32_t transform = 0;
         switch (mOrientation) {
             case DisplayState::eOrientationDefault:
-                transform = Transform::ROT_0;
+                transform = ui::Transform::ROT_0;
                 break;
             case DisplayState::eOrientation90:
-                transform = Transform::ROT_90;
+                transform = ui::Transform::ROT_90;
                 break;
             case DisplayState::eOrientation180:
-                transform = Transform::ROT_180;
+                transform = ui::Transform::ROT_180;
                 break;
             case DisplayState::eOrientation270:
-                transform = Transform::ROT_270;
+                transform = ui::Transform::ROT_270;
                 break;
         }
         sPrimaryDisplayOrientation = transform;
@@ -656,7 +656,7 @@
 }
 
 void DisplayDevice::dump(String8& result) const {
-    const Transform& tr(mGlobalTransform);
+    const ui::Transform& tr(mGlobalTransform);
     ANativeWindow* const window = mNativeWindow.get();
     result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.c_str());
     result.appendFormat("   type=%x, ID=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index f440d29..bcb2976 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -17,19 +17,20 @@
 #ifndef ANDROID_DISPLAY_DEVICE_H
 #define ANDROID_DISPLAY_DEVICE_H
 
-#include "Transform.h"
-
 #include <stdlib.h>
+
+#include <memory>
+#include <string>
 #include <unordered_map>
 
-#include <math/mat4.h>
-
 #include <binder/IBinder.h>
-#include <gui/ISurfaceComposer.h>
 #include <hardware/hwcomposer_defs.h>
+#include <gui/ISurfaceComposer.h>
+#include <math/mat4.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
+#include <ui/Transform.h>
 #include <utils/RefBase.h>
 #include <utils/Mutex.h>
 #include <utils/String8.h>
@@ -38,9 +39,6 @@
 #include "RenderArea.h"
 #include "RenderEngine/Surface.h"
 
-#include <memory>
-#include <string>
-
 struct ANativeWindow;
 
 namespace android {
@@ -126,7 +124,7 @@
     int                     getOrientation() const { return mOrientation; }
     uint32_t                getOrientationTransform() const;
     static uint32_t         getPrimaryDisplayOrientationTransform();
-    const Transform&        getTransform() const { return mGlobalTransform; }
+    const ui::Transform&   getTransform() const { return mGlobalTransform; }
     const Rect              getViewport() const { return mViewport; }
     const Rect              getFrame() const { return mFrame; }
     const Rect&             getScissor() const { return mScissor; }
@@ -254,7 +252,7 @@
      * Transaction state
      */
     static status_t orientationToTransfrom(int orientation,
-            int w, int h, Transform* tr);
+                                           int w, int h, ui::Transform* tr);
 
     // The identifier of the active layer stack for this display. Several displays
     // can use the same layer stack: A z-ordered group of layers (sometimes called
@@ -269,7 +267,7 @@
     Rect mFrame;
     // pre-computed scissor to apply to the display
     Rect mScissor;
-    Transform mGlobalTransform;
+    ui::Transform mGlobalTransform;
     bool mNeedsFiltering;
     // Current power mode
     int mPowerMode;
@@ -344,7 +342,7 @@
           : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device),
                               mSourceCrop(sourceCrop) {}
 
-    const Transform& getTransform() const override { return mDevice->getTransform(); }
+    const ui::Transform& getTransform() const override { return mDevice->getTransform(); }
     Rect getBounds() const override { return mDevice->getBounds(); }
     int getHeight() const override { return mDevice->getHeight(); }
     int getWidth() const override { return mDevice->getWidth(); }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 35cbda0..1a2566e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -295,7 +295,7 @@
         win.intersect(crop, &win);
     }
 
-    Transform t = getTransform();
+    ui::Transform t = getTransform();
     win = t.transform(win);
 
     Rect finalCrop = getFinalCrop(s);
@@ -349,7 +349,7 @@
         parentBounds = p->computeBounds(Region());
     }
 
-    Transform t = s.active_legacy.transform;
+    ui::Transform t = s.active_legacy.transform;
 
     if (p != nullptr || !s.finalCrop_legacy.isEmpty()) {
         floatWin = t.transform(floatWin);
@@ -383,7 +383,7 @@
         activeCrop.intersect(crop, &activeCrop);
     }
 
-    Transform t = getTransform();
+    ui::Transform t = getTransform();
     activeCrop = t.transform(activeCrop);
     if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
         activeCrop.clear();
@@ -414,7 +414,7 @@
 
     // Screen space to make reduction to parent crop clearer.
     Rect activeCrop = computeInitialCrop(display);
-    Transform t = getTransform();
+    ui::Transform t = getTransform();
     // Back to layer space to work with the content crop.
     activeCrop = t.inverse().transform(activeCrop);
 
@@ -446,7 +446,8 @@
             invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
         }
         // and apply to the current transform
-        invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation();
+        invTransform = (ui::Transform(invTransformOrient) *
+                        ui::Transform(invTransform)).getOrientation();
     }
 
     int winWidth = getActiveWidth(s);
@@ -515,11 +516,12 @@
              " %s (%d)",
              mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(),
              static_cast<int32_t>(error));
+    getBE().compositionInfo.hwc.blendMode = blendMode;
 
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
     Region activeTransparentRegion(getActiveTransparentRegion(s));
-    Transform t = getTransform();
+    ui::Transform t = getTransform();
     Rect activeCrop = getCrop(s);
     if (!activeCrop.isEmpty()) {
         activeCrop = t.transform(activeCrop);
@@ -557,7 +559,7 @@
     if (!frame.intersect(display->getViewport(), &frame)) {
         frame.clear();
     }
-    const Transform& tr = display->getTransform();
+    const ui::Transform& tr = display->getTransform();
     Rect transformedFrame = tr.transform(frame);
     error = hwcLayer->setDisplayFrame(transformedFrame);
     if (error != HWC2::Error::None) {
@@ -567,6 +569,7 @@
     } else {
         hwcInfo.displayFrame = transformedFrame;
     }
+    getBE().compositionInfo.hwc.displayFrame = transformedFrame;
 
     FloatRect sourceCrop = computeCrop(display);
     error = hwcLayer->setSourceCrop(sourceCrop);
@@ -578,6 +581,7 @@
     } else {
         hwcInfo.sourceCrop = sourceCrop;
     }
+    getBE().compositionInfo.hwc.sourceCrop = sourceCrop;
 
     float alpha = static_cast<float>(getAlpha());
     error = hwcLayer->setPlaneAlpha(alpha);
@@ -585,10 +589,12 @@
              "[%s] Failed to set plane alpha %.3f: "
              "%s (%d)",
              mName.string(), alpha, to_string(error).c_str(), static_cast<int32_t>(error));
+    getBE().compositionInfo.hwc.alpha = alpha;
 
     error = hwcLayer->setZOrder(z);
     ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", mName.string(), z,
              to_string(error).c_str(), static_cast<int32_t>(error));
+    getBE().compositionInfo.hwc.z = z;
 
     int type = s.type;
     int appId = s.appId;
@@ -605,6 +611,9 @@
     ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(),
              static_cast<int32_t>(error));
 
+    getBE().compositionInfo.hwc.type = type;
+    getBE().compositionInfo.hwc.appId = appId;
+
     /*
      * Transformations are applied in this order:
      * 1) buffer orientation/flip/mirror
@@ -613,8 +622,8 @@
      * (NOTE: the matrices are multiplied in reverse order)
      */
 
-    const Transform bufferOrientation(mCurrentTransform);
-    Transform transform(tr * t * bufferOrientation);
+    const ui::Transform bufferOrientation(mCurrentTransform);
+    ui::Transform transform(tr * t * bufferOrientation);
 
     if (getTransformToDisplayInverse()) {
         /*
@@ -633,14 +642,15 @@
          * computation so it's enough to just omit it in the composition.
          * See comment in onDraw with ref to b/36727915 for why.
          */
-        transform = Transform(invTransform) * tr * bufferOrientation;
+        transform = ui::Transform(invTransform) * tr * bufferOrientation;
     }
 
     // this gives us only the "orientation" component of the transform
     const uint32_t orientation = transform.getOrientation();
-    if (orientation & Transform::ROT_INVALID) {
+    if (orientation & ui::Transform::ROT_INVALID) {
         // we can only handle simple transformation
         hwcInfo.forceClientComposition = true;
+        getBE().mHwcLayers[displayId].compositionType = HWC2::Composition::Client;
     } else {
         auto transform = static_cast<HWC2::Transform>(orientation);
         hwcInfo.transform = transform;
@@ -650,6 +660,7 @@
                  "%s (%d)",
                  mName.string(), to_string(transform).c_str(), to_string(error).c_str(),
                  static_cast<int32_t>(error));
+        getBE().compositionInfo.hwc.transform = transform;
     }
 }
 
@@ -761,16 +772,12 @@
 }
 
 HWC2::Composition Layer::getCompositionType(int32_t displayId) const {
-    if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+    if (getBE().mHwcLayers.count(displayId) == 0) {
         // If we're querying the composition type for a display that does not
         // have a HWC counterpart, then it will always be Client
         return HWC2::Composition::Client;
     }
-    if (getBE().mHwcLayers.count(displayId) == 0) {
-        ALOGE("getCompositionType called with an invalid HWC layer");
-        return HWC2::Composition::Invalid;
-    }
-    return getBE().mHwcLayers.at(displayId).compositionType;
+    return getBE().mHwcLayers[displayId].compositionType;
 }
 
 void Layer::setClearClientTarget(int32_t displayId, bool clear) {
@@ -831,7 +838,7 @@
 void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh,
                             bool useIdentityTransform) const {
     const Layer::State& s(getDrawingState());
-    const Transform renderAreaTransform(renderArea.getTransform());
+    const ui::Transform renderAreaTransform(renderArea.getTransform());
     const uint32_t height = renderArea.getHeight();
     FloatRect win = computeBounds();
 
@@ -840,7 +847,7 @@
     vec2 rb = vec2(win.right, win.bottom);
     vec2 rt = vec2(win.right, win.top);
 
-    Transform layerTransform = getTransform();
+    ui::Transform layerTransform = getTransform();
     if (!useIdentityTransform) {
         lt = layerTransform.transform(lt);
         lb = layerTransform.transform(lb);
@@ -1104,7 +1111,7 @@
 
         // we may use linear filtering, if the matrix scales us
         const uint8_t type = getActiveTransform(c).getType();
-        mNeedsFiltering = (!getActiveTransform(c).preserveRects() || (type >= Transform::SCALE));
+        mNeedsFiltering = (!getActiveTransform(c).preserveRects() || type >= ui::Transform::SCALE);
     }
 
     // If the layer is hidden, signal and clear out all local sync points so
@@ -1279,7 +1286,7 @@
 
 bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix,
         bool allowNonRectPreservingTransforms) {
-    Transform t;
+    ui::Transform t;
     t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
 
     if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
@@ -1418,9 +1425,9 @@
         // The transform hint is used to improve performance, but we can
         // only have a single transform hint, it cannot
         // apply to all displays.
-        const Transform& planeTransform = display->getTransform();
+        const ui::Transform& planeTransform = display->getTransform();
         orientation = planeTransform.getOrientation();
-        if (orientation & Transform::ROT_INVALID) {
+        if (orientation & ui::Transform::ROT_INVALID) {
             orientation = 0;
         }
     }
@@ -1526,6 +1533,12 @@
     const FloatRect& crop = hwcInfo.sourceCrop;
     result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom);
 
+    result.append("- - - - - - - - - - - - - - - -\n");
+
+    std::string compositionInfoStr;
+    getBE().compositionInfo.dump(compositionInfoStr, "compositionInfo");
+    result.append(compositionInfoStr.c_str());
+
     result.append("- - - - - - - - - - - - - - - -");
     result.append("- - - - - - - - - - - - - - - -");
     result.append("- - - - - - - - - - - - - - -\n");
@@ -1885,8 +1898,8 @@
     traverseChildrenInZOrderInner(layersInTree, stateSet, visitor);
 }
 
-Transform Layer::getTransform() const {
-    Transform t;
+ui::Transform Layer::getTransform() const {
+    ui::Transform t;
     const auto& p = mDrawingParent.promote();
     if (p != nullptr) {
         t = p->getTransform();
@@ -1908,7 +1921,7 @@
             }
             float sx = p->getActiveWidth(p->getDrawingState()) / static_cast<float>(bufferWidth);
             float sy = p->getActiveHeight(p->getDrawingState()) / static_cast<float>(bufferHeight);
-            Transform extraParentScaling;
+            ui::Transform extraParentScaling;
             extraParentScaling.set(sx, 0, 0, sy);
             t = t * extraParentScaling;
         }
@@ -1942,8 +1955,8 @@
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
     const State& state = useDrawing ? mDrawingState : mCurrentState;
 
-    Transform requestedTransform = state.active_legacy.transform;
-    Transform transform = getTransform();
+    ui::Transform requestedTransform = state.active_legacy.transform;
+    ui::Transform transform = getTransform();
 
     layerInfo->set_id(sequence);
     layerInfo->set_name(getName().c_str());
@@ -2011,7 +2024,7 @@
     auto buffer = getBE().compositionInfo.mBuffer;
     if (buffer != nullptr) {
         LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer());
-        LayerProtoHelper::writeToProto(Transform(mCurrentTransform),
+        LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform),
                                        layerInfo->mutable_buffer_transform());
     }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 814adf7..56ed765 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -28,10 +28,11 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 #include <ui/Region.h>
+#include <ui/Transform.h>
 
+#include <gui/BufferQueue.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/LayerState.h>
-#include <gui/BufferQueue.h>
 
 #include <list>
 #include <cstdint>
@@ -43,7 +44,6 @@
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
 #include "TimeStats/TimeStats.h"
-#include "Transform.h"
 
 #include <layerproto/LayerProtoHeader.h>
 #include "DisplayHardware/HWComposer.h"
@@ -101,7 +101,7 @@
     struct Geometry {
         uint32_t w;
         uint32_t h;
-        Transform transform;
+        ui::Transform transform;
 
         inline bool operator==(const Geometry& rhs) const {
             return (w == rhs.w && h == rhs.h) && (transform.tx() == rhs.transform.tx()) &&
@@ -345,7 +345,7 @@
     virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
     virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
     virtual uint32_t getActiveHeight(const Layer::State& s) const { return s.active_legacy.h; }
-    virtual Transform getActiveTransform(const Layer::State& s) const {
+    virtual ui::Transform getActiveTransform(const Layer::State& s) const {
         return s.active_legacy.transform;
     }
     virtual Region getActiveTransparentRegion(const Layer::State& s) const {
@@ -513,6 +513,14 @@
         return getBE().mHwcLayers[displayId].layer.get();
     }
 
+    bool setHwcLayer(int32_t hwcId) {
+        if (getBE().mHwcLayers.count(hwcId) == 0) {
+            return false;
+        }
+        getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[hwcId].layer;
+        return true;
+    }
+
     // -----------------------------------------------------------------------
 
     void clearWithOpenGL(const RenderArea& renderArea) const;
@@ -545,7 +553,7 @@
 
     virtual bool getTransformToDisplayInverse() const { return false; }
 
-    Transform getTransform() const;
+    ui::Transform getTransform() const;
 
     // Returns the Alpha of the Surface, accounting for the Alpha
     // of parent Surfaces in the hierarchy (alpha's will be multiplied
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index b936b3f..6381a44 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -20,6 +20,11 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include "Layer.h"
+#include "RenderEngine/RenderEngine.h"
+
+#include "android-base/stringprintf.h"
+
+#include <string>
 
 namespace android {
 
@@ -41,50 +46,94 @@
     mLayer->onLayerDisplayed(releaseFence);
 }
 
-void CompositionInfo::dumpHwc(const char* tag) const {
-    ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer.get());
-    ALOGV("[%s]\tfence=%p", tag, hwc.fence.get());
-    ALOGV("[%s]\ttransform=%d", tag, hwc.transform);
-    ALOGV("[%s]\tz=%d", tag, hwc.z);
-    ALOGV("[%s]\ttype=%d", tag, hwc.type);
-    ALOGV("[%s]\tappId=%d", tag, hwc.appId);
-    ALOGV("[%s]\tdisplayFrame=%4d %4d %4d %4d", tag, hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom);
-    ALOGV("[%s]\talpha=%.3f", tag, hwc.alpha);
-    ALOGV("[%s]\tsourceCrop=%6.1f %6.1f %6.1f %6.1f", tag, hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
-
-    std::string label = tag;
-    label+=":visibleRegion";
-    hwc.visibleRegion.dump(label.c_str());
-    label = tag;
-    label+=":surfaceDamage";
-    hwc.surfaceDamage.dump(label.c_str());
+void CompositionInfo::dump(const char* tag) const
+{
+    std::string logString;
+    dump(logString, tag);
+    ALOGV("%s", logString.c_str());
 }
 
-void CompositionInfo::dumpRe(const char* tag) const {
-    ALOGV("[%s]\tblackoutLayer=%d", tag, re.blackoutLayer);
-    ALOGV("[%s]\tclearArea=%d", tag, re.clearArea);
-    ALOGV("[%s]\tpreMultipliedAlpha=%d", tag, re.preMultipliedAlpha);
-    ALOGV("[%s]\topaque=%d", tag, re.opaque);
-    ALOGV("[%s]\tdisableTexture=%d", tag, re.disableTexture);
-    ALOGV("[%s]\ttexture:name(%d), target(%d), size(%d/%d)", tag, re.texture.getTextureName(), re.texture.getTextureTarget(), (unsigned int)re.texture.getWidth(), (unsigned int)re.texture.getHeight());
-    ALOGV("[%s]\tuseIdentityTransform=%d\n", tag, re.useIdentityTransform);
+void CompositionInfo::dumpHwc(std::string& result, const char* tag) const {
+    if (tag == nullptr) {
+        result += base::StringPrintf("HWC parameters\n");
+    } else {
+        result += base::StringPrintf("[%s]HWC parameters\n", tag);
+    }
+
+    result += base::StringPrintf("\thwcLayer=%p\n", static_cast<HWC2::Layer*>(&*hwc.hwcLayer));
+    result += base::StringPrintf("\tfence=%p\n", hwc.fence.get());
+    result += base::StringPrintf("\tblendMode=%d\n", hwc.blendMode);
+    result += base::StringPrintf("\ttransform=%d\n", hwc.transform);
+    result += base::StringPrintf("\tz=%d\n", hwc.z);
+    result += base::StringPrintf("\ttype=%d\n", hwc.type);
+    result += base::StringPrintf("\tappId=%d\n", hwc.appId);
+    result += base::StringPrintf("\tdisplayFrame=%4d %4d %4d %4d\n", hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom);
+    result += base::StringPrintf("\talpha=%.3f", hwc.alpha);
+    result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
+
+    {
+        //
+        // Keep a conversion from std::string to String8 and back until Region can use std::string
+        //
+        String8 regionString;
+        hwc.visibleRegion.dump(regionString, "visibleRegion");
+        hwc.surfaceDamage.dump(regionString, "surfaceDamage");
+        result += regionString.string();
+    }
 }
 
-void CompositionInfo::dump(const char* tag) const {
-    ALOGV("[%s] CompositionInfo", tag);
-    ALOGV("[%s]\tLayerName: %s", tag, layerName.c_str());
-    ALOGV("[%s]\tCompositionType: %d", tag, compositionType);
-    ALOGV("[%s]\tmBuffer = %p", tag, mBuffer.get());
-    ALOGV("[%s]\tmBufferSlot=%d", tag, mBufferSlot);
+void CompositionInfo::dumpRe(std::string& result, const char* tag) const {
+    if (tag == nullptr) {
+        result += base::StringPrintf("RenderEngine parameters:\n");
+    } else {
+        result += base::StringPrintf("[%s]RenderEngine parameters:\n", tag);
+    }
+
+    Mesh& mesh = layer->getMesh();
+    result += base::StringPrintf("\tblackoutLayer=%d\n", re.blackoutLayer);
+    result += base::StringPrintf("\tclearArea=%d\n", re.clearArea);
+    result += base::StringPrintf("\tpreMultipliedAlpha=%d\n", re.preMultipliedAlpha);
+    result += base::StringPrintf("\topaque=%d\n", re.opaque);
+    result += base::StringPrintf("\tdisableTexture=%d\n", re.disableTexture);
+    result += base::StringPrintf("\ttexture:name(%d), target(%d), size(%d/%d)\n", re.texture.getTextureName(), re.texture.getTextureTarget(), (unsigned int)re.texture.getWidth(), (unsigned int)re.texture.getHeight());
+    result += base::StringPrintf("\tuseIdentityTransform=%d\n", re.useIdentityTransform);
+    Mesh::VertexArray<vec2> positions(mesh.getPositionArray<vec2>());
+    result += base::StringPrintf("\tpositions[(%6.1f,%6.1f), (%6.1f,%6.1f), (%6.1f,%6.1f), (%6.1f,%6.1f)]\n",
+            positions[0][0], positions[0][1], positions[1][0], positions[1][1],
+            positions[2][0], positions[2][1], positions[3][0], positions[3][1]);
+    Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
+    result += base::StringPrintf("\ttexCoords[(%6.1f,%6.1f), (%6.1f,%6.1f),(%6.1f,%6.1f),(%6.1f,%6.1f)]\n",
+        texCoords[0][0], texCoords[0][1], texCoords[1][0], texCoords[1][1],
+        texCoords[2][0], texCoords[2][1], texCoords[3][0], texCoords[3][1]);
+}
+
+void CompositionInfo::dump(std::string& result, const char* tag) const
+{
+    if (tag == nullptr) {
+        result += base::StringPrintf("CompositionInfo\n");
+    } else {
+        result += base::StringPrintf("[%s]CompositionInfo\n", tag);
+    }
+    result += base::StringPrintf("\tLayerName: %s\n", layerName.c_str());
+    result += base::StringPrintf("\tCompositionType: %d\n", compositionType);
+    result += base::StringPrintf("\tmBuffer = %p\n", mBuffer.get());
+    result += base::StringPrintf("\tmBufferSlot=%d\n", mBufferSlot);
+    result += base::StringPrintf("\tdisplayFrame=%4d %4d %4d %4d\n", hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom);
+    result += base::StringPrintf("\talpha=%f\n", hwc.alpha);
+    result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
+
     switch (compositionType) {
         case HWC2::Composition::Device:
-            dumpHwc(tag);
+            dumpHwc(result, tag);
             break;
         case HWC2::Composition::Client:
-            dumpRe(tag);
+            dumpRe(result, tag);
+            break;
         default:
             break;
     }
 }
 
+
+
 }; // namespace android
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 3055621..86d4ac4 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -40,6 +40,7 @@
     std::shared_ptr<LayerBE> layer;
     struct {
         std::shared_ptr<HWC2::Layer> hwcLayer;
+        int32_t displayId = -1;
         sp<Fence> fence;
         HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid;
         Rect displayFrame;
@@ -55,6 +56,8 @@
         ui::Dataspace dataspace;
         hwc_color_t color;
         bool clearClientTarget = false;
+        bool supportedPerFrameMetadata = false;
+        HdrMetadata hdrMetadata;
     } hwc;
     struct {
         Mesh* mesh;
@@ -70,8 +73,9 @@
     } re;
 
     void dump(const char* tag) const;
-    void dumpHwc(const char* tag) const;
-    void dumpRe(const char* tag) const;
+    void dump(std::string& result, const char* tag = nullptr) const;
+    void dumpHwc(std::string& result, const char* tag = nullptr) const;
+    void dumpRe(std::string& result, const char* tag = nullptr) const;
 };
 
 class LayerBE {
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index cc39550..3289e8f 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -51,7 +51,8 @@
     colorProto->set_a(color.a);
 }
 
-void LayerProtoHelper::writeToProto(const Transform& transform, TransformProto* transformProto) {
+void LayerProtoHelper::writeToProto(const ui::Transform& transform,
+                                    TransformProto* transformProto) {
     transformProto->set_dsdx(transform[0][0]);
     transformProto->set_dtdx(transform[0][1]);
     transformProto->set_dsdy(transform[1][0]);
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
index 860da63..6df5aea 100644
--- a/services/surfaceflinger/LayerProtoHelper.h
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -16,13 +16,11 @@
 
 #include <layerproto/LayerProtoHeader.h>
 
+#include <math/vec4.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
-
-#include <Transform.h>
-
-#include <math/vec4.h>
+#include <ui/Transform.h>
 
 namespace android {
 namespace surfaceflinger {
@@ -32,7 +30,7 @@
     static void writeToProto(const FloatRect& rect, FloatRectProto* rectProto);
     static void writeToProto(const Region& region, RegionProto* regionProto);
     static void writeToProto(const half4 color, ColorProto* colorProto);
-    static void writeToProto(const Transform& transform, TransformProto* transformProto);
+    static void writeToProto(const ui::Transform& transform, TransformProto* transformProto);
     static void writeToProto(const sp<GraphicBuffer>& buffer, ActiveBufferProto* activeBufferProto);
 };
 
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index bd59d17..136cdc0 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -50,13 +50,13 @@
 
     // check that we received a buffer of the right size
     // (Take the buffer's orientation into account)
-    if (item.mTransform & Transform::ROT_90) {
+    if (item.mTransform & ui::Transform::ROT_90) {
         std::swap(bufWidth, bufHeight);
     }
 
     if (mTransformToDisplayInverse) {
         uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
-        if (invTransform & Transform::ROT_90) {
+        if (invTransform & ui::Transform::ROT_90) {
             std::swap(bufWidth, bufHeight);
         }
     }
diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
index 1a8edf3..7f69ce4 100644
--- a/services/surfaceflinger/RenderArea.cpp
+++ b/services/surfaceflinger/RenderArea.cpp
@@ -4,6 +4,27 @@
 
 namespace android {
 
+ui::Transform::orientation_flags fromRotation(ISurfaceComposer::Rotation rotation) {
+    switch (rotation) {
+        case ISurfaceComposer::eRotateNone:
+            return ui::Transform::ROT_0;
+        case ISurfaceComposer::eRotate90:
+            return ui::Transform::ROT_90;
+        case ISurfaceComposer::eRotate180:
+            return ui::Transform::ROT_180;
+        case ISurfaceComposer::eRotate270:
+            return ui::Transform::ROT_270;
+    }
+    ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
+    return ui::Transform::ROT_0;
+}
+
+RenderArea::RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill,
+                       ISurfaceComposer::Rotation rotation)
+      : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) {
+    mRotationFlags = fromRotation(rotation);
+}
+
 float RenderArea::getCaptureFillValue(CaptureFill captureFill) {
     switch(captureFill) {
         case CaptureFill::CLEAR:
@@ -23,7 +44,7 @@
     uint32_t width = getWidth();
     uint32_t height = getHeight();
 
-    if (mRotationFlags & Transform::ROT_90) {
+    if (mRotationFlags & ui::Transform::ROT_90) {
         std::swap(width, height);
     }
 
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 96e4b5f..e38f462 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -1,8 +1,8 @@
 #pragma once
 
+#include <gui/ISurfaceComposer.h>
 #include <ui/GraphicTypes.h>
-
-#include "Transform.h"
+#include <ui/Transform.h>
 
 #include <functional>
 
@@ -16,14 +16,11 @@
     static float getCaptureFillValue(CaptureFill captureFill);
 
     RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill,
-               ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
-          : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) {
-        mRotationFlags = Transform::fromRotation(rotation);
-    }
+               ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone);
 
     virtual ~RenderArea() = default;
 
-    virtual const Transform& getTransform() const = 0;
+    virtual const ui::Transform& getTransform() const = 0;
     virtual Rect getBounds() const = 0;
     virtual int getHeight() const = 0;
     virtual int getWidth() const = 0;
@@ -35,7 +32,7 @@
 
     int getReqHeight() const { return mReqHeight; };
     int getReqWidth() const { return mReqWidth; };
-    Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
+    ui::Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
     status_t updateDimensions(int displayRotation);
 
     CaptureFill getCaptureFill() const { return mCaptureFill; };
@@ -43,7 +40,7 @@
 private:
     uint32_t mReqHeight;
     uint32_t mReqWidth;
-    Transform::orientation_flags mRotationFlags;
+    ui::Transform::orientation_flags mRotationFlags;
     CaptureFill mCaptureFill;
 };
 
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index c218e4d..d4a2bb4 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -19,9 +19,6 @@
 
 #include <utils/TypeHelpers.h>
 
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
 #include "Description.h"
 
 namespace android {
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 4860f3c..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());
@@ -167,7 +167,7 @@
 
 void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
                                                   size_t hwh, bool yswap,
-                                                  Transform::orientation_flags rotation) {
+                                                  ui::Transform::orientation_flags rotation) {
     int32_t l = sourceCrop.left;
     int32_t r = sourceCrop.right;
 
@@ -185,15 +185,15 @@
     // Apply custom rotation to the projection.
     float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
     switch (rotation) {
-        case Transform::ROT_0:
+        case ui::Transform::ROT_0:
             break;
-        case Transform::ROT_90:
+        case ui::Transform::ROT_90:
             m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m;
             break;
-        case Transform::ROT_180:
+        case ui::Transform::ROT_180:
             m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m;
             break;
-        case Transform::ROT_270:
+        case ui::Transform::ROT_270:
             m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m;
             break;
         default:
@@ -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 cc8eb1d..d8cb73b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -21,7 +21,6 @@
 #include <sys/types.h>
 
 #include <GLES2/gl2.h>
-#include <Transform.h>
 
 #include "Description.h"
 #include "ProgramCache.h"
@@ -67,7 +66,7 @@
 protected:
     virtual void dump(String8& result);
     virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh,
-                                          bool yswap, Transform::orientation_flags rotation);
+                                          bool yswap, ui::Transform::orientation_flags rotation);
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
                                     const half4& color) override;
 
@@ -95,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 d2b218e..6213784 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -24,9 +24,10 @@
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
-#include <Transform.h>
 #include <android-base/unique_fd.h>
 #include <math/mat4.h>
+#include <ui/GraphicTypes.h>
+#include <ui/Transform.h>
 
 #define EGL_NO_CONFIG ((EGLConfig)0)
 
@@ -55,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;
@@ -105,7 +106,7 @@
     // set-up
     virtual void checkErrors() const;
     virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh,
-                                          bool yswap, Transform::orientation_flags rotation) = 0;
+                                          bool yswap, ui::Transform::orientation_flags rotation) = 0;
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
                                     const half4& color) = 0;
     virtual void setupLayerTexturing(const Texture& texture) = 0;
diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp
index 0d20f1f..3bf42fb 100644
--- a/services/surfaceflinger/RenderEngine/Surface.cpp
+++ b/services/surfaceflinger/RenderEngine/Surface.cpp
@@ -19,6 +19,7 @@
 #include "RenderEngine.h"
 
 #include <log/log.h>
+#include <ui/PixelFormat.h>
 
 namespace android {
 namespace RE {
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 61f2ac8..697d634 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
 #include "DispSyncSource.h"
 
 #include <android-base/stringprintf.h>
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a83fb25..a779289 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -91,8 +91,11 @@
 
 #include <cutils/compiler.h>
 
+#include "android-base/stringprintf.h"
+
 #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 +179,7 @@
 int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
 // TODO(courtneygo): Rename hasWideColorDisplay to clarify its actual meaning.
 bool SurfaceFlinger::hasWideColorDisplay;
+bool SurfaceFlinger::useColorManagement;
 
 
 std::string getHwcServiceName() {
@@ -259,8 +263,6 @@
         mDebugDDMS(0),
         mDebugDisableHWC(0),
         mDebugDisableTransformHint(0),
-        mDebugInSwapBuffers(0),
-        mLastSwapBufferTime(0),
         mDebugInTransaction(0),
         mLastTransactionTime(0),
         mForceFullDamage(false),
@@ -304,6 +306,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>(
@@ -599,11 +603,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,
@@ -876,6 +879,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) {
@@ -1435,25 +1453,26 @@
     return false;
 }
 
-bool SurfaceFlinger::handleMessageInvalidate() {
-    ATRACE_CALL();
-    return handlePageFlip();
-}
-
 void SurfaceFlinger::handleMessageRefresh() {
     ATRACE_CALL();
 
     mRefreshPending = false;
 
+    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
     preComposition();
     rebuildLayerStacks();
     calculateWorkingSet();
-    beginFrame();
-    prepareFrame();
-    doDebugFlashRegions();
+    for (const auto& [token, display] : mDisplays) {
+        beginFrame(display);
+        prepareFrame(display);
+        doDebugFlashRegions(display, repaintEverything);
+        doComposition(display, repaintEverything);
+    }
+
     doTracing("handleRefresh");
     logLayerStats();
-    doComposition();
+
+    postFrame();
     postComposition();
 
     mHadClientComposition = false;
@@ -1461,11 +1480,26 @@
         mHadClientComposition = mHadClientComposition ||
                 getBE().mHwc->hasClientComposition(display->getId());
     }
+
     mVsyncModulator.onRefreshed(mHadClientComposition);
 
+    getBE().mEndOfFrameCompositionInfo = std::move(getBE().mCompositionInfo);
+    for (const auto& [token, display] : mDisplays) {
+        const auto displayId = display->getId();
+        for (auto& compositionInfo : getBE().mEndOfFrameCompositionInfo[displayId]) {
+            compositionInfo.hwc.hwcLayer = nullptr;
+        }
+    }
+
     mLayersWithQueuedFrames.clear();
 }
 
+
+bool SurfaceFlinger::handleMessageInvalidate() {
+    ATRACE_CALL();
+    return handlePageFlip();
+}
+
 void SurfaceFlinger::calculateWorkingSet() {
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
@@ -1532,7 +1566,7 @@
             layer->setPerFrameData(display);
         }
 
-        if (hasWideColorDisplay) {
+        if (useColorManagement) {
             ColorMode  colorMode;
             Dataspace dataSpace;
             RenderIntent renderIntent;
@@ -1542,46 +1576,56 @@
     }
 
     mDrawingState.colorMatrixChanged = false;
+
+    for (const auto& [token, display] : mDisplays) {
+        const auto displayId = display->getId();
+        getBE().mCompositionInfo[displayId].clear();
+        for (auto& layer : display->getVisibleLayersSortedByZ()) {
+            auto displayId = display->getId();
+            layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId);
+            if (!layer->setHwcLayer(displayId)) {
+                ALOGV("Need to create HWCLayer for %s", layer->getName().string());
+            }
+            layer->getBE().compositionInfo.hwc.displayId = displayId;
+            getBE().mCompositionInfo[displayId].push_back(layer->getBE().compositionInfo);
+            layer->getBE().compositionInfo.hwc.hwcLayer = nullptr;
+        }
+    }
 }
 
-void SurfaceFlinger::doDebugFlashRegions()
+void SurfaceFlinger::doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything)
 {
     // is debugging enabled
     if (CC_LIKELY(!mDebugRegion))
         return;
 
-    const bool repaintEverything = mRepaintEverything;
-    for (const auto& [token, display] : mDisplays) {
-        if (display->isPoweredOn()) {
-            // transform the dirty region into this screen's coordinate space
-            const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
-            if (!dirtyRegion.isEmpty()) {
-                // redraw the whole screen
-                doComposeSurfaces(display);
+    if (display->isPoweredOn()) {
+        // transform the dirty region into this screen's coordinate space
+        const Region dirtyRegion(display->getDirtyRegion(repaintEverything));
+        if (!dirtyRegion.isEmpty()) {
+            // redraw the whole screen
+            doComposeSurfaces(display);
 
-                // and draw the dirty region
-                const int32_t height = display->getHeight();
-                auto& engine(getRenderEngine());
-                engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
+            // and draw the dirty region
+            const int32_t height = display->getHeight();
+            auto& engine(getRenderEngine());
+            engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
 
-                display->swapBuffers(getHwComposer());
-            }
+            display->swapBuffers(getHwComposer());
         }
     }
 
-    postFramebuffer();
+    postFramebuffer(display);
 
     if (mDebugRegion > 1) {
         usleep(mDebugRegion * 1000);
     }
 
-    for (const auto& [token, display] : mDisplays) {
-        if (!display->isPoweredOn()) {
-            continue;
-        }
-
+    if (display->isPoweredOn()) {
         status_t result = display->prepareFrame(*getBE().mHwc);
-        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
+        ALOGE_IF(result != NO_ERROR,
+                 "prepareFrame for display %d failed:"
+                 " %d (%s)",
                  display->getId(), result, strerror(-result));
     }
 }
@@ -1821,7 +1865,7 @@
             Region dirtyRegion;
             Vector<sp<Layer>> layersSortedByZ;
             Vector<sp<Layer>> layersNeedingFences;
-            const Transform& tr = display->getTransform();
+            const ui::Transform& tr = display->getTransform();
             const Rect bounds = display->getBounds();
             if (display->isPoweredOn()) {
                 computeVisibleRegions(display, dirtyRegion, opaqueRegion);
@@ -1945,80 +1989,85 @@
     display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
 }
 
-void SurfaceFlinger::beginFrame()
+void SurfaceFlinger::beginFrame(const sp<DisplayDevice>& display)
 {
-    for (const auto& [token, display] : mDisplays) {
-        bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty();
-        bool empty = display->getVisibleLayersSortedByZ().size() == 0;
-        bool wasEmpty = !display->lastCompositionHadVisibleLayers;
+    bool dirty = !display->getDirtyRegion(false).isEmpty();
+    bool empty = display->getVisibleLayersSortedByZ().size() == 0;
+    bool wasEmpty = !display->lastCompositionHadVisibleLayers;
 
-        // If nothing has changed (!dirty), don't recompose.
-        // If something changed, but we don't currently have any visible layers,
-        //   and didn't when we last did a composition, then skip it this time.
-        // The second rule does two things:
-        // - When all layers are removed from a display, we'll emit one black
-        //   frame, then nothing more until we get new layers.
-        // - When a display is created with a private layer stack, we won't
-        //   emit any black frames until a layer is added to the layer stack.
-        bool mustRecompose = dirty && !(empty && wasEmpty);
+    // If nothing has changed (!dirty), don't recompose.
+    // If something changed, but we don't currently have any visible layers,
+    //   and didn't when we last did a composition, then skip it this time.
+    // The second rule does two things:
+    // - When all layers are removed from a display, we'll emit one black
+    //   frame, then nothing more until we get new layers.
+    // - When a display is created with a private layer stack, we won't
+    //   emit any black frames until a layer is added to the layer stack.
+    bool mustRecompose = dirty && !(empty && wasEmpty);
 
-        ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)",
-                 display->getId(), mustRecompose ? "doing" : "skipping", dirty ? "+" : "-",
-                 empty ? "+" : "-", wasEmpty ? "+" : "-");
+    ALOGV_IF(display->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
+            "id[%d]: %s composition (%sdirty %sempty %swasEmpty)", display->getId(),
+            mustRecompose ? "doing" : "skipping",
+            dirty ? "+" : "-",
+            empty ? "+" : "-",
+            wasEmpty ? "+" : "-");
 
-        display->beginFrame(mustRecompose);
+    display->beginFrame(mustRecompose);
 
-        if (mustRecompose) {
-            display->lastCompositionHadVisibleLayers = !empty;
-        }
+    if (mustRecompose) {
+        display->lastCompositionHadVisibleLayers = !empty;
     }
 }
 
-void SurfaceFlinger::prepareFrame()
+void SurfaceFlinger::prepareFrame(const sp<DisplayDevice>& display)
 {
-    for (const auto& [token, display] : mDisplays) {
-        if (!display->isPoweredOn()) {
-            continue;
-        }
-
-        status_t result = display->prepareFrame(*getBE().mHwc);
-        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
-                 display->getId(), result, strerror(-result));
+    if (!display->isPoweredOn()) {
+        return;
     }
+
+    status_t result = display->prepareFrame(*getBE().mHwc);
+    ALOGE_IF(result != NO_ERROR,
+             "prepareFrame for display %d failed:"
+             " %d (%s)",
+             display->getId(), result, strerror(-result));
 }
 
-void SurfaceFlinger::doComposition() {
+void SurfaceFlinger::doComposition(const sp<DisplayDevice>& display, bool repaintEverything) {
     ATRACE_CALL();
     ALOGV("doComposition");
 
-    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
-    for (const auto& [token, display] : mDisplays) {
-        if (display->isPoweredOn()) {
-            // transform the dirty region into this screen's coordinate space
-            const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
+    if (display->isPoweredOn()) {
+        // transform the dirty region into this screen's coordinate space
+        const Region dirtyRegion(display->getDirtyRegion(repaintEverything));
 
-            // repaint the framebuffer (if needed)
-            doDisplayComposition(display, dirtyRegion);
+        // repaint the framebuffer (if needed)
+        doDisplayComposition(display, dirtyRegion);
 
-            display->dirtyRegion.clear();
-            display->flip();
-        }
+        display->dirtyRegion.clear();
+        display->flip();
     }
-    postFramebuffer();
+    postFramebuffer(display);
 }
 
-void SurfaceFlinger::postFramebuffer()
+void SurfaceFlinger::postFrame()
+{
+    // |mStateLock| not needed as we are on the main thread
+    if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
+        uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
+        if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
+            logFrameStats();
+        }
+    }
+}
+
+void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& display)
 {
     ATRACE_CALL();
     ALOGV("postFramebuffer");
 
-    const nsecs_t now = systemTime();
-    mDebugInSwapBuffers = now;
+    mPostFramebufferTime = systemTime();
 
-    for (const auto& [token, display] : mDisplays) {
-        if (!display->isPoweredOn()) {
-            continue;
-        }
+    if (display->isPoweredOn()) {
         const auto displayId = display->getId();
         if (displayId >= 0) {
             getBE().mHwc->presentAndGetReleaseFences(displayId);
@@ -2063,18 +2112,6 @@
             getBE().mHwc->clearReleaseFences(displayId);
         }
     }
-
-    mLastSwapBufferTime = systemTime() - now;
-    mDebugInSwapBuffers = 0;
-
-    // |mStateLock| not needed as we are on the main thread
-    const auto display = getDefaultDisplayDeviceLocked();
-    if (display && getHwComposer().isConnected(display->getId())) {
-        const uint32_t flipCount = display->getPageFlipCount();
-        if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
-            logFrameStats();
-        }
-    }
 }
 
 void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
@@ -2189,7 +2226,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)) {
@@ -2639,7 +2676,7 @@
             const bool translucent = !layer->isOpaque(s);
             Rect bounds(layer->computeScreenBounds());
             visibleRegion.set(bounds);
-            Transform tr = layer->getTransform();
+            ui::Transform tr = layer->getTransform();
             if (!visibleRegion.isEmpty()) {
                 // Remove the transparent area from the visible region
                 if (translucent) {
@@ -2656,7 +2693,7 @@
                 // compute the opaque region
                 const int32_t layerOrientation = tr.getOrientation();
                 if (layer->getAlpha() == 1.0f && !translucent &&
-                        ((layerOrientation & Transform::ROT_INVALID) == false)) {
+                        ((layerOrientation & ui::Transform::ROT_INVALID) == false)) {
                     // the opaque region is the layer's footprint
                     opaqueRegion = visibleRegion;
                 }
@@ -2895,22 +2932,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());
         }
     }
 
@@ -2919,7 +2951,7 @@
      */
 
     ALOGV("Rendering client layers");
-    const Transform& displayTransform = display->getTransform();
+    const ui::Transform& displayTransform = display->getTransform();
     bool firstLayer = true;
     for (auto& layer : display->getVisibleLayersSortedByZ()) {
         const Region clip(bounds.intersect(
@@ -3896,6 +3928,13 @@
             }
 
             if ((index < numArgs) &&
+                    (args[index] == String16("--frame-composition"))) {
+                index++;
+                dumpFrameCompositionInfo(result);
+                dumpAll = false;
+            }
+
+            if ((index < numArgs) &&
                 (args[index] == String16("--display-identification"))) {
                 index++;
                 dumpDisplayIdentificationData(result);
@@ -4127,7 +4166,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());
 
@@ -4152,6 +4192,31 @@
     result.append("\n");
 }
 
+void SurfaceFlinger::dumpFrameCompositionInfo(String8& result) const {
+    std::string stringResult;
+
+    for (const auto& [token, display] : mDisplays) {
+        const auto displayId = display->getId();
+        if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+            continue;
+        }
+
+        const auto& compositionInfoIt = getBE().mEndOfFrameCompositionInfo.find(displayId);
+        if (compositionInfoIt == getBE().mEndOfFrameCompositionInfo.end()) {
+            break;
+        }
+        const auto& compositionInfoList = compositionInfoIt->second;
+        stringResult += base::StringPrintf("Display: %d\n", displayId);
+        stringResult += base::StringPrintf("numComponents: %zu\n", compositionInfoList.size());
+        for (const auto& compositionInfo : compositionInfoList) {
+            compositionInfo.dump(stringResult, nullptr);
+            stringResult += base::StringPrintf("\n");
+        }
+    }
+
+    result.append(stringResult.c_str());
+}
+
 LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const {
     LayersProto layersProto;
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
@@ -4200,9 +4265,7 @@
 
     // figure out if we're stuck somewhere
     const nsecs_t now = systemTime();
-    const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
     const nsecs_t inTransaction(mDebugInTransaction);
-    nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
     nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
 
     /*
@@ -4252,7 +4315,7 @@
                 appEarlyOffset,
                 sfEarlyOffset,
                 appEarlyGlOffset,
-                sfEarlyOffset,
+                sfEarlyGlOffset,
                 dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
     }
     result.append("\n");
@@ -4280,6 +4343,10 @@
     result.append(LayerProtoParser::layersToString(std::move(layerTree)).c_str());
     result.append("\n");
 
+    result.append("\nFrame-Composition information:\n");
+    dumpFrameCompositionInfo(result);
+    result.append("\n");
+
     /*
      * Dump Display state
      */
@@ -4310,11 +4377,8 @@
         result.appendFormat("  orientation=%d, isPoweredOn=%d\n", display->getOrientation(),
                             display->isPoweredOn());
     }
-    result.appendFormat("  last eglSwapBuffers() time: %f us\n"
-                        "  last transaction time     : %f us\n"
-                        "  transaction-flags         : %08x\n"
+    result.appendFormat("  transaction-flags         : %08x\n"
                         "  gpu_to_cpu_unsupported    : %d\n",
-                        mLastSwapBufferTime / 1000.0, mLastTransactionTime / 1000.0,
                         mTransactionFlags, !mGpuToCpuSupported);
 
     if (display) {
@@ -4326,9 +4390,6 @@
                             activeConfig->getDpiY());
     }
 
-    result.appendFormat("  eglSwapBuffers time: %f us\n",
-            inSwapBuffersDuration/1000.0);
-
     result.appendFormat("  transaction time: %f us\n",
             inTransactionDuration/1000.0);
 
@@ -4441,7 +4502,6 @@
     switch (static_cast<ISurfaceComposerTag>(code)) {
         // These methods should at minimum make sure that the client requested
         // access to SF.
-        case AUTHENTICATE_SURFACE:
         case BOOT_FINISHED:
         case CLEAR_ANIMATION_FRAME_STATS:
         case CREATE_CONNECTION:
@@ -4478,11 +4538,13 @@
         // The following calls are currently used by clients that do not
         // request necessary permissions. However, they do not expose any secret
         // information, so it is OK to pass them.
+        case AUTHENTICATE_SURFACE:
         case GET_ACTIVE_CONFIG:
         case GET_BUILT_IN_DISPLAY:
         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.
@@ -4709,7 +4771,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;
             }
@@ -4741,7 +4805,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);
@@ -4789,6 +4853,11 @@
                 ATRACE_INT("PeriodDivisor", divisor);
                 return NO_ERROR;
             }
+            // Is device color managed?
+            case 1030: {
+                reply->writeBool(useColorManagement);
+                return NO_ERROR;
+            }
         }
     }
     return err;
@@ -4824,6 +4893,16 @@
     const auto display = getDisplayDeviceLocked(displayToken);
     if (!display) return BAD_VALUE;
 
+    const Rect& dispScissor = display->getScissor();
+    if (!dispScissor.isEmpty()) {
+        sourceCrop.set(dispScissor);
+        // adb shell screencap will default reqWidth and reqHeight to zeros.
+        if (reqWidth == 0 || reqHeight == 0) {
+            reqWidth = uint32_t(display->getViewport().width());
+            reqHeight = uint32_t(display->getViewport().height());
+        }
+    }
+
     DisplayRenderArea renderArea(display, sourceCrop, reqHeight, reqWidth, rotation);
 
     auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
@@ -4845,7 +4924,7 @@
                 mCrop(crop),
                 mFlinger(flinger),
                 mChildrenOnly(childrenOnly) {}
-        const Transform& getTransform() const override { return mTransform; }
+        const ui::Transform& getTransform() const override { return mTransform; }
         Rect getBounds() const override {
             const Layer::State& layerState(mLayer->getDrawingState());
             return Rect(mLayer->getActiveWidth(layerState), mLayer->getActiveHeight(layerState));
@@ -4897,7 +4976,7 @@
         // In the "childrenOnly" case we reparent the children to a screenshot
         // layer which has no properties set and which does not draw.
         sp<ContainerLayer> screenshotParentLayer;
-        Transform mTransform;
+        ui::Transform mTransform;
 
         SurfaceFlinger* mFlinger;
         const bool mChildrenOnly;
@@ -5051,17 +5130,17 @@
         sourceCrop.setLeftTop(Point(0, 0));
         sourceCrop.setRightBottom(Point(raWidth, raHeight));
     } else if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) {
-        Transform tr;
+        ui::Transform tr;
         uint32_t flags = 0x00;
         switch (mPrimaryDisplayOrientation) {
             case DisplayState::eOrientation90:
-                flags = Transform::ROT_90;
+                flags = ui::Transform::ROT_90;
                 break;
             case DisplayState::eOrientation180:
-                flags = Transform::ROT_180;
+                flags = ui::Transform::ROT_180;
                 break;
             case DisplayState::eOrientation270:
-                flags = Transform::ROT_270;
+                flags = ui::Transform::ROT_270;
                 break;
         }
         tr.set(flags, raWidth, raHeight);
@@ -5089,7 +5168,7 @@
     // make sure to clear all GL error flags
     engine.checkErrors();
 
-    Transform::orientation_flags rotation = renderArea.getRotationFlags();
+    ui::Transform::orientation_flags rotation = renderArea.getRotationFlags();
     if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) {
         // convert hw orientation into flag presentation
         // here inverse transform needed
@@ -5097,26 +5176,26 @@
         uint8_t hw_flip_hv = 0x00;
         switch (mPrimaryDisplayOrientation) {
             case DisplayState::eOrientation90:
-                hw_rot_90 = Transform::ROT_90;
-                hw_flip_hv = Transform::ROT_180;
+                hw_rot_90 = ui::Transform::ROT_90;
+                hw_flip_hv = ui::Transform::ROT_180;
                 break;
             case DisplayState::eOrientation180:
-                hw_flip_hv = Transform::ROT_180;
+                hw_flip_hv = ui::Transform::ROT_180;
                 break;
             case DisplayState::eOrientation270:
-                hw_rot_90  = Transform::ROT_90;
+                hw_rot_90  = ui::Transform::ROT_90;
                 break;
         }
 
         // transform flags operation
         // 1) flip H V if both have ROT_90 flag
         // 2) XOR these flags
-        uint8_t rotation_rot_90  = rotation & Transform::ROT_90;
-        uint8_t rotation_flip_hv = rotation & Transform::ROT_180;
+        uint8_t rotation_rot_90  = rotation & ui::Transform::ROT_90;
+        uint8_t rotation_flip_hv = rotation & ui::Transform::ROT_180;
         if (rotation_rot_90 & hw_rot_90) {
-            rotation_flip_hv = (~rotation_flip_hv) & Transform::ROT_180;
+            rotation_flip_hv = (~rotation_flip_hv) & ui::Transform::ROT_180;
         }
-        rotation = static_cast<Transform::orientation_flags>
+        rotation = static_cast<ui::Transform::orientation_flags>
                    ((rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv));
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f5d8eb4..ed9e212 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -100,6 +100,7 @@
 class Surface;
 class SurfaceFlingerBE;
 class VSyncSource;
+struct CompositionInfo;
 
 namespace impl {
 class EventThread;
@@ -224,6 +225,9 @@
     // use to differentiate callbacks from different hardware composer
     // instances. Each hardware composer instance gets a different sequence id.
     int32_t mComposerSequenceId;
+
+    std::unordered_map<int32_t, std::vector<CompositionInfo>> mCompositionInfo;
+    std::unordered_map<int32_t, std::vector<CompositionInfo>> mEndOfFrameCompositionInfo;
 };
 
 
@@ -280,13 +284,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";
     }
@@ -431,6 +435,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);
@@ -673,14 +678,14 @@
      * prior to any CompositionInfo handling and is not dependent on data in
      * CompositionInfo
      */
-    void beginFrame();
+    void beginFrame(const sp<DisplayDevice>& display);
     /* prepareFrame - This function will call into the DisplayDevice to prepare a
      * frame after CompositionInfo has been programmed.   This provides a mechanism
      * to prepare the hardware composer
      */
-    void prepareFrame();
-    void doComposition();
-    void doDebugFlashRegions();
+    void prepareFrame(const sp<DisplayDevice>& display);
+    void doComposition(const sp<DisplayDevice>& display, bool repainEverything);
+    void doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything);
     void doTracing(const char* where);
     void logLayerStats();
     void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion);
@@ -688,7 +693,8 @@
     // This fails if using GL and the surface has been destroyed.
     bool doComposeSurfaces(const sp<const DisplayDevice>& display);
 
-    void postFramebuffer();
+    void postFramebuffer(const sp<DisplayDevice>& display);
+    void postFrame();
     void drawWormhole(const sp<const DisplayDevice>& display, const Region& region) const;
 
     /* ------------------------------------------------------------------------
@@ -749,6 +755,7 @@
     void dumpBufferingStats(String8& result) const;
     void dumpDisplayIdentificationData(String8& result) const;
     void dumpWideColorInfo(String8& result) const;
+    void dumpFrameCompositionInfo(String8& result) const;
     LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
     LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& display) const;
 
@@ -844,9 +851,9 @@
     int mDebugDisableHWC;
     int mDebugDisableTransformHint;
     volatile nsecs_t mDebugInSwapBuffers;
-    nsecs_t mLastSwapBufferTime;
     volatile nsecs_t mDebugInTransaction;
     nsecs_t mLastTransactionTime;
+    nsecs_t mPostFramebufferTime;
     bool mForceFullDamage;
     bool mPropagateBackpressure = true;
     std::unique_ptr<SurfaceInterceptor> mInterceptor =
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
deleted file mode 100644
index b11d057..0000000
--- a/services/surfaceflinger/Transform.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#ifndef ANDROID_TRANSFORM_H
-#define ANDROID_TRANSFORM_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <ui/Point.h>
-#include <ui/Rect.h>
-#include <math/vec2.h>
-#include <math/vec3.h>
-
-#include <gui/ISurfaceComposer.h>
-
-#include <hardware/hardware.h>
-
-namespace android {
-
-class Region;
-
-// ---------------------------------------------------------------------------
-
-class Transform
-{
-public:
-                    Transform();
-                    Transform(const Transform&  other);
-           explicit Transform(uint32_t orientation);
-                    ~Transform();
-
-            enum orientation_flags {
-                ROT_0   = 0x00000000,
-                FLIP_H  = HAL_TRANSFORM_FLIP_H,
-                FLIP_V  = HAL_TRANSFORM_FLIP_V,
-                ROT_90  = HAL_TRANSFORM_ROT_90,
-                ROT_180 = FLIP_H|FLIP_V,
-                ROT_270 = ROT_180|ROT_90,
-                ROT_INVALID = 0x80
-            };
-
-            static orientation_flags fromRotation(ISurfaceComposer::Rotation rotation);
-
-            enum type_mask {
-                IDENTITY            = 0,
-                TRANSLATE           = 0x1,
-                ROTATE              = 0x2,
-                SCALE               = 0x4,
-                UNKNOWN             = 0x8
-            };
-
-            // query the transform
-            bool        preserveRects() const;
-            uint32_t    getType() const;
-            uint32_t    getOrientation() const;
-
-            const vec3& operator [] (size_t i) const;  // returns column i
-            float   tx() const;
-            float   ty() const;
-
-            // modify the transform
-            void        reset();
-            void        set(float tx, float ty);
-            void        set(float a, float b, float c, float d);
-            status_t    set(uint32_t flags, float w, float h);
-
-            // transform data
-            Rect    makeBounds(int w, int h) const;
-            vec2    transform(int x, int y) const;
-            Region  transform(const Region& reg) const;
-            Rect    transform(const Rect& bounds,
-                    bool roundOutwards = false) const;
-            FloatRect transform(const FloatRect& bounds) const;
-            Transform operator * (const Transform& rhs) const;
-            // assumes the last row is < 0 , 0 , 1 >
-            vec2 transform(const vec2& v) const;
-            vec3 transform(const vec3& v) const;
-
-            Transform inverse() const;
-
-            // for debugging
-            void dump(const char* name) const;
-
-private:
-    struct mat33 {
-        vec3 v[3];
-        inline const vec3& operator [] (int i) const { return v[i]; }
-        inline vec3& operator [] (int i) { return v[i]; }
-    };
-
-    enum { UNKNOWN_TYPE = 0x80000000 };
-
-    uint32_t type() const;
-    static bool absIsOne(float f);
-    static bool isZero(float f);
-
-    mat33               mMatrix;
-    mutable uint32_t    mType;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif /* ANDROID_TRANSFORM_H */
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/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index cd57411..8e23eb8e 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -287,7 +287,15 @@
 }
 
 /**
- * Test for methods accessible directly through SurfaceFlinger:
+ * The following tests are for methods accessible directly through SurfaceFlinger.
+ */
+
+/**
+ * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
+ * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
+ * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
+ * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
+ * the consumer of a buffer queue is SurfaceFlinger.
  */
 TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
     setupBackgroundSurface();
@@ -296,7 +304,8 @@
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
 
     std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
-    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+    // Anyone should be able to check if the consumer of the buffer queue is SF.
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
 }
 
 TEST_F(CredentialsTest, GetLayerDebugInfo) {
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; }
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 7814d32..36f74b6 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -56,7 +56,7 @@
     MOCK_METHOD5(readPixels, void(size_t, size_t, size_t, size_t, uint32_t*));
     MOCK_CONST_METHOD0(checkErrors, void());
     MOCK_METHOD6(setViewportAndProjection,
-                 void(size_t, size_t, Rect, size_t, bool, Transform::orientation_flags));
+                 void(size_t, size_t, Rect, size_t, bool, ui::Transform::orientation_flags));
     MOCK_METHOD4(setupLayerBlending, void(bool, bool, bool, const half4&));
     MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
     MOCK_METHOD0(setupLayerBlackedOut, void());