Merge "SF: Set the buffer size immediately when applying a transaction"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 2c248c6..9216e75 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1464,6 +1464,12 @@
             DUMPSYS_COMPONENTS_OPTIONS);
 
     printf("========================================================\n");
+    printf("== Checkins\n");
+    printf("========================================================\n");
+
+    RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
+
+    printf("========================================================\n");
     printf("== dumpstate: done (id %d)\n", ds.id_);
     printf("========================================================\n");
 }
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 d0ac8de..b8465e3 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -839,6 +839,10 @@
     return NO_ERROR;
 }
 
+status_t SurfaceComposerClient::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
+    return ComposerService::getComposerService()->getDisplayViewport(display, outViewport);
+}
+
 int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) {
     return ComposerService::getComposerService()->getActiveConfig(display);
 }
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 98ec338..b9158f1 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -157,6 +157,9 @@
     virtual status_t getDisplayStats(const sp<IBinder>& display,
             DisplayStatInfo* stats) = 0;
 
+    /* returns display viewport information of the given display */
+    virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) = 0;
+
     /* indicates which of the configurations returned by getDisplayInfo is
      * currently active */
     virtual int getActiveConfig(const sp<IBinder>& display) = 0;
@@ -250,7 +253,8 @@
         ENABLE_VSYNC_INJECTIONS,
         INJECT_VSYNC,
         GET_LAYER_DEBUG_INFO,
-        CREATE_SCOPED_CONNECTION
+        CREATE_SCOPED_CONNECTION,
+        GET_DISPLAY_VIEWPORT
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 4907866..9bd1131 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -79,6 +79,9 @@
     static status_t getDisplayInfo(const sp<IBinder>& display,
             DisplayInfo* info);
 
+    // Get the display viewport for the given display
+    static status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
+
     // Get the index of the current active configuration (relative to the list
     // returned by getDisplayInfo)
     static int getActiveConfig(const sp<IBinder>& display);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3542aba..f22e702 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -581,6 +581,9 @@
             Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
     status_t getDisplayStats(const sp<IBinder>& /*display*/,
             DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
+    status_t getDisplayViewport(const sp<IBinder>& /*display*/, Rect* /*outViewport*/) override {
+        return NO_ERROR;
+    }
     int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; }
     status_t setActiveConfig(const sp<IBinder>& /*display*/, int /*id*/)
             override {
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 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 efaeaa2..05535a5 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",
@@ -54,6 +55,7 @@
         "libvulkan",
     ],
     static_libs: [
+        "librenderengine",
         "libserviceutils",
         "libtrace_proto",
         "libvkjson",
@@ -65,6 +67,7 @@
         "android.hardware.graphics.composer@2.2-command-buffer",
     ],
     export_static_lib_headers: [
+        "librenderengine",
         "libserviceutils",
     ],
     export_shared_lib_headers: [
@@ -117,16 +120,6 @@
         "LayerVector.cpp",
         "MonitoredProducer.cpp",
         "RenderArea.cpp",
-        "RenderEngine/Description.cpp",
-        "RenderEngine/GLES20RenderEngine.cpp",
-        "RenderEngine/GLExtensions.cpp",
-        "RenderEngine/Image.cpp",
-        "RenderEngine/Mesh.cpp",
-        "RenderEngine/Program.cpp",
-        "RenderEngine/ProgramCache.cpp",
-        "RenderEngine/RenderEngine.cpp",
-        "RenderEngine/Surface.cpp",
-        "RenderEngine/Texture.cpp",
         "Scheduler/DispSync.cpp",
         "Scheduler/DispSyncSource.cpp",
         "Scheduler/EventControlThread.cpp",
@@ -175,6 +168,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 e1094d8..d0ccabb 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -24,7 +24,7 @@
 #include "DisplayDevice.h"
 #include "LayerRejecter.h"
 
-#include "RenderEngine/RenderEngine.h"
+#include <renderengine/RenderEngine.h>
 
 #include <gui/BufferItem.h>
 #include <gui/BufferQueue.h>
@@ -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);
 }
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 0b641b7..3319a98 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -24,13 +24,12 @@
 #include "FrameTracker.h"
 #include "LayerVector.h"
 #include "MonitoredProducer.h"
-#include "RenderEngine/Mesh.h"
-#include "RenderEngine/Texture.h"
 #include "SurfaceFlinger.h"
 
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/LayerState.h>
-
+#include <renderengine/Mesh.h>
+#include <renderengine/Texture.h>
 #include <ui/FrameStats.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 9096d4c..aa8f4e1 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -20,10 +20,7 @@
 //#define LOG_NDEBUG 0
 
 #include "BufferLayerConsumer.h"
-
 #include "Layer.h"
-#include "RenderEngine/Image.h"
-#include "RenderEngine/RenderEngine.h"
 #include "Scheduler/DispSync.h"
 
 #include <inttypes.h>
@@ -38,9 +35,9 @@
 #include <gui/GLConsumer.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
-
 #include <private/gui/ComposerService.h>
-
+#include <renderengine/Image.h>
+#include <renderengine/RenderEngine.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/Trace.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 369ad89..da9dcfb 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -20,9 +20,9 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include "BufferStateLayer.h"
-#include "RenderEngine/Image.h"
 
 #include <private/gui/SyncFeatures.h>
+#include <renderengine/Image.h>
 
 namespace android {
 
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index e492375..038eb01 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -16,13 +16,12 @@
 
 #pragma once
 
-#include "RenderEngine/Image.h"
-#include "RenderEngine/RenderEngine.h"
-
 #include "BufferLayer.h"
 #include "Layer.h"
 
 #include <gui/GLConsumer.h>
+#include <renderengine/Image.h>
+#include <renderengine/RenderEngine.h>
 #include <system/window.h>
 #include <utils/String8.h>
 
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 7eeaabb..c29698b 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -22,14 +22,13 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
+#include <renderengine/RenderEngine.h>
+#include <ui/GraphicBuffer.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
-#include <ui/GraphicBuffer.h>
-
 #include "ColorLayer.h"
 #include "DisplayDevice.h"
-#include "RenderEngine/RenderEngine.h"
 #include "SurfaceFlinger.h"
 
 namespace android {
@@ -89,6 +88,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 +97,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 +107,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 +117,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 776b84a..0fbd459 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -18,6 +18,8 @@
 #undef LOG_TAG
 #define LOG_TAG "DisplayDevice"
 
+#include "DisplayDevice.h"
+
 #include <array>
 #include <unordered_set>
 
@@ -26,31 +28,24 @@
 #include <string.h>
 #include <math.h>
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
 #include <cutils/properties.h>
-
-#include <utils/RefBase.h>
-#include <utils/Log.h>
-
+#include <gui/Surface.h>
+#include <hardware/gralloc.h>
+#include <renderengine/RenderEngine.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayInfo.h>
 #include <ui/PixelFormat.h>
-
-#include <gui/Surface.h>
-
-#include <hardware/gralloc.h>
+#include <utils/RefBase.h>
+#include <utils/Log.h>
 
 #include "DisplayHardware/DisplaySurface.h"
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/HWC2.h"
-#include "RenderEngine/RenderEngine.h"
-
-#include "DisplayDevice.h"
 #include "SurfaceFlinger.h"
 #include "Layer.h"
 
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
-#include <configstore/Utils.h>
-
 namespace android {
 
 // retrieve triple buffer setting from configstore
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index bcb2976..4290988 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -25,8 +25,8 @@
 
 #include <binder/IBinder.h>
 #include <hardware/hwcomposer_defs.h>
-#include <gui/ISurfaceComposer.h>
 #include <math/mat4.h>
+#include <renderengine/Surface.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
 #include <ui/Region.h>
@@ -37,7 +37,6 @@
 #include <utils/Timers.h>
 
 #include "RenderArea.h"
-#include "RenderEngine/Surface.h"
 
 struct ANativeWindow;
 
@@ -334,12 +333,12 @@
 class DisplayRenderArea : public RenderArea {
 public:
     DisplayRenderArea(const sp<const DisplayDevice> device,
-                      ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
-          : DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(),
+                      ui::Transform::orientation_flags rotation = ui::Transform::ROT_0)
+          : DisplayRenderArea(device, device->getBounds(), device->getWidth(), device->getHeight(),
                               rotation) {}
-    DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqHeight,
-                      uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
-          : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device),
+    DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqWidth,
+                      uint32_t reqHeight, ui::Transform::orientation_flags rotation)
+          : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, rotation), mDevice(device),
                               mSourceCrop(sourceCrop) {}
 
     const ui::Transform& getTransform() const override { return mDevice->getTransform(); }
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index ef31908..a32ff6e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -184,6 +184,7 @@
 
         auto newDisplay = std::make_unique<Display>(
                 *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, displayType);
+        newDisplay->setFrequencyScaleParameters(mFrequencyScaler);
         newDisplay->setConnected(true);
         mDisplays.emplace(displayId, std::move(newDisplay));
     } else if (connection == Connection::Disconnected) {
@@ -223,6 +224,14 @@
     return static_cast<Error>(mComposer->executeCommands());
 }
 
+void Device::setDisplayFrequencyScaleParameters(Device::FrequencyScaler frequencyScaler) {
+    mFrequencyScaler = frequencyScaler;
+}
+
+Device::FrequencyScaler Device::getDisplayFrequencyScaleParameters() {
+    return mFrequencyScaler;
+}
+
 // Display methods
 
 Display::Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
@@ -262,6 +271,7 @@
     mWidth(-1),
     mHeight(-1),
     mVsyncPeriod(-1),
+    mFrequencyScaler(display.mFrequencyScaler),
     mDpiX(-1),
     mDpiY(-1) {}
 
@@ -701,6 +711,10 @@
     mIsConnected = connected;
 }
 
+void Display::setFrequencyScaleParameters(Device::FrequencyScaler frequencyScaler) {
+    mFrequencyScaler = frequencyScaler;
+}
+
 int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
 {
     int32_t value = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index e0d6ecc..a8f24d6 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -85,6 +85,11 @@
 public:
     explicit Device(std::unique_ptr<android::Hwc2::Composer> composer);
 
+    struct FrequencyScaler {
+        int32_t multiplier = 1;
+        int32_t divisor = 1;
+    };
+
     void registerCallback(ComposerCallback* callback, int32_t sequenceId);
 
     // Required by HWC2
@@ -116,6 +121,9 @@
     // This method provides an explicit way to flush state changes to HWC.
     Error flushCommands();
 
+    void setDisplayFrequencyScaleParameters(FrequencyScaler frequecyScaler);
+    FrequencyScaler getDisplayFrequencyScaleParameters();
+
 private:
     // Initialization methods
 
@@ -126,6 +134,7 @@
     std::unordered_set<Capability> mCapabilities;
     std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
     android::Hwc2::impl::PowerAdvisor mPowerAdvisor;
+    FrequencyScaler mFrequencyScaler;
     bool mRegisteredCallback = false;
 };
 
@@ -161,8 +170,6 @@
             }
             Builder& setVsyncPeriod(int32_t vsyncPeriod) {
                 mConfig->mVsyncPeriod = vsyncPeriod;
-                mConfig->mPeriodMultiplier = 1;
-                mConfig->mPeriodDivisor = 1;
                 return *this;
             }
             Builder& setDpiX(int32_t dpiX) {
@@ -193,11 +200,7 @@
         int32_t getWidth() const { return mWidth; }
         int32_t getHeight() const { return mHeight; }
         nsecs_t getVsyncPeriod() const {
-            return mVsyncPeriod * mPeriodMultiplier / mPeriodDivisor; }
-        void scalePanelFrequency(int32_t multiplier, int32_t divisor) const {
-            mPeriodMultiplier = multiplier;
-            mPeriodDivisor = divisor;
-        }
+            return mVsyncPeriod * mFrequencyScaler.multiplier / mFrequencyScaler.divisor; }
         float getDpiX() const { return mDpiX; }
         float getDpiY() const { return mDpiY; }
 
@@ -210,8 +213,7 @@
         int32_t mWidth;
         int32_t mHeight;
         nsecs_t mVsyncPeriod;
-        mutable int32_t mPeriodMultiplier;
-        mutable int32_t mPeriodDivisor;
+        Device::FrequencyScaler mFrequencyScaler;
         float mDpiX;
         float mDpiY;
     };
@@ -279,6 +281,7 @@
     hwc2_display_t getId() const { return mId; }
     bool isConnected() const { return mIsConnected; }
     void setConnected(bool connected);  // For use by Device only
+    void setFrequencyScaleParameters(Device::FrequencyScaler frequencyScaler);
 
 private:
     int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
@@ -303,6 +306,7 @@
     hwc2_display_t mId;
     bool mIsConnected;
     DisplayType mType;
+    Device::FrequencyScaler mFrequencyScaler;
     std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
     std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
 };
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index bf8905a..630cc0b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -807,4 +807,15 @@
     return mDisplayData[displayId].hwcDisplay->getId();
 }
 
+void HWComposer::setDisplayFrequencyScaleParameters(
+        HWC2::Device::FrequencyScaler frequencyScaler)
+{
+    mHwcDevice->setDisplayFrequencyScaleParameters(frequencyScaler);
+}
+
+HWC2::Device::FrequencyScaler HWComposer::getDisplayFrequencyScaleParameters()
+{
+    return mHwcDevice->getDisplayFrequencyScaleParameters();
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3c5efea..9e01626 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -184,6 +184,14 @@
     android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
 
     std::optional<hwc2_display_t> getHwcDisplayId(int32_t displayId) const;
+
+    // ------------------------------------------------------------------------
+    // These functions set and get the frequencyScaler.  The frequencyScaler holds
+    // a multiplier and divisor for virtually scaling the panel frequency in
+    // software.  This is used to simulate different panel frequencies when
+    // panel hardware is not available.
+    void setDisplayFrequencyScaleParameters(HWC2::Device::FrequencyScaler frequencyScaler);
+    HWC2::Device::FrequencyScaler getDisplayFrequencyScaleParameters();
 private:
     // For unit tests
     friend TestableSurfaceFlinger;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 04beae0..68b5a31 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -53,7 +53,7 @@
 
 #include "DisplayHardware/HWComposer.h"
 
-#include "RenderEngine/RenderEngine.h"
+#include <renderengine/RenderEngine.h>
 
 #include <mutex>
 #include "LayerProtoHelper.h"
@@ -516,6 +516,7 @@
              " %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
@@ -568,6 +569,7 @@
     } else {
         hwcInfo.displayFrame = transformedFrame;
     }
+    getBE().compositionInfo.hwc.displayFrame = transformedFrame;
 
     FloatRect sourceCrop = computeCrop(display);
     error = hwcLayer->setSourceCrop(sourceCrop);
@@ -579,6 +581,7 @@
     } else {
         hwcInfo.sourceCrop = sourceCrop;
     }
+    getBE().compositionInfo.hwc.sourceCrop = sourceCrop;
 
     float alpha = static_cast<float>(getAlpha());
     error = hwcLayer->setPlaneAlpha(alpha);
@@ -586,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;
@@ -606,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
@@ -642,6 +650,7 @@
     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;
@@ -651,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;
     }
 }
 
@@ -762,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) {
@@ -1527,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");
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6ebd668..443f410 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -19,23 +19,26 @@
 
 #include <sys/types.h>
 
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Timers.h>
-
+#include <gui/BufferQueue.h>
+#include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
+#include <layerproto/LayerProtoHeader.h>
+#include <math/vec4.h>
+#include <renderengine/Mesh.h>
+#include <renderengine/Texture.h>
 #include <ui/FloatRect.h>
 #include <ui/FrameStats.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 #include <ui/Region.h>
 #include <ui/Transform.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
 
-#include <gui/BufferQueue.h>
-#include <gui/ISurfaceComposerClient.h>
-#include <gui/LayerState.h>
-
-#include <list>
 #include <cstdint>
+#include <list>
+#include <vector>
 
 #include "Client.h"
 #include "FrameTracker.h"
@@ -45,15 +48,9 @@
 #include "SurfaceFlinger.h"
 #include "TimeStats/TimeStats.h"
 
-#include <layerproto/LayerProtoHeader.h>
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/HWComposerBufferCache.h"
 #include "RenderArea.h"
-#include "RenderEngine/Mesh.h"
-#include "RenderEngine/Texture.h"
-
-#include <math/vec4.h>
-#include <vector>
 
 using namespace android::surfaceflinger;
 
@@ -513,6 +510,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;
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index b936b3f..3e04f26 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -21,6 +21,11 @@
 
 #include "Layer.h"
 
+#include <android-base/stringprintf.h>
+#include <renderengine/RenderEngine.h>
+
+#include <string>
+
 namespace android {
 
 LayerBE::LayerBE(Layer* layer, std::string layerName)
@@ -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..e5110b7 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -19,14 +19,13 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <renderengine/Mesh.h>
+#include <renderengine/Texture.h>
 #include <ui/Region.h>
 
-#include "SurfaceFlinger.h"
-
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/HWComposerBufferCache.h"
-#include "RenderEngine/Mesh.h"
-#include "RenderEngine/Texture.h"
+#include "SurfaceFlinger.h"
 
 namespace android {
 
@@ -40,6 +39,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 +55,8 @@
         ui::Dataspace dataspace;
         hwc_color_t color;
         bool clearClientTarget = false;
+        bool supportedPerFrameMetadata = false;
+        HdrMetadata hdrMetadata;
     } hwc;
     struct {
         Mesh* mesh;
@@ -70,8 +72,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/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
index 7f69ce4..93759e8 100644
--- a/services/surfaceflinger/RenderArea.cpp
+++ b/services/surfaceflinger/RenderArea.cpp
@@ -1,30 +1,7 @@
 #include "RenderArea.h"
 
-#include <gui/LayerState.h>
-
 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:
@@ -34,37 +11,5 @@
             return 1.0f;
     }
 }
-/*
- * Checks that the requested width and height are valid and updates them to the render area
- * dimensions if they are set to 0
- */
-status_t RenderArea::updateDimensions(int displayRotation) {
-    // get screen geometry
-
-    uint32_t width = getWidth();
-    uint32_t height = getHeight();
-
-    if (mRotationFlags & ui::Transform::ROT_90) {
-        std::swap(width, height);
-    }
-
-    if (displayRotation & DisplayState::eOrientationSwapMask) {
-        std::swap(width, height);
-    }
-
-    if ((mReqWidth > width) || (mReqHeight > height)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)", mReqWidth, mReqHeight, width, height);
-        return BAD_VALUE;
-    }
-
-    if (mReqWidth == 0) {
-        mReqWidth = width;
-    }
-    if (mReqHeight == 0) {
-        mReqHeight = height;
-    }
-
-    return NO_ERROR;
-}
 
 } // namespace android
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index e38f462..3c11e73 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -1,47 +1,80 @@
 #pragma once
 
-#include <gui/ISurfaceComposer.h>
-#include <ui/GraphicTypes.h>
 #include <ui/Transform.h>
 
 #include <functional>
 
 namespace android {
 
+// RenderArea describes a rectangular area that layers can be rendered to.
+//
+// There is a logical render area and a physical render area.  When a layer is
+// rendered to the render area, it is first transformed and clipped to the logical
+// render area.  The transformed and clipped layer is then projected onto the
+// physical render area.
 class RenderArea {
-
 public:
     enum class CaptureFill {CLEAR, OPAQUE};
 
     static float getCaptureFillValue(CaptureFill captureFill);
 
-    RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill,
-               ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone);
+    RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill,
+               ui::Transform::orientation_flags rotation = ui::Transform::ROT_0)
+          : mReqWidth(reqWidth),
+            mReqHeight(reqHeight),
+            mCaptureFill(captureFill),
+            mRotationFlags(rotation) {}
 
     virtual ~RenderArea() = default;
 
-    virtual const ui::Transform& getTransform() const = 0;
-    virtual Rect getBounds() const = 0;
-    virtual int getHeight() const = 0;
-    virtual int getWidth() const = 0;
-    virtual bool isSecure() const = 0;
-    virtual bool needsFiltering() const = 0;
-    virtual Rect getSourceCrop() const = 0;
-
+    // Invoke drawLayers to render layers into the render area.
     virtual void render(std::function<void()> drawLayers) { drawLayers(); }
 
-    int getReqHeight() const { return mReqHeight; };
-    int getReqWidth() const { return mReqWidth; };
-    ui::Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
-    status_t updateDimensions(int displayRotation);
+    // Returns true if the render area is secure.  A secure layer should be
+    // blacked out / skipped when rendered to an insecure render area.
+    virtual bool isSecure() const = 0;
 
+    // Returns true if the otherwise disabled layer filtering should be
+    // enabled when rendering to this render area.
+    virtual bool needsFiltering() const = 0;
+
+    // Returns the transform to be applied on layers to transform them into
+    // the logical render area.
+    virtual const ui::Transform& getTransform() const = 0;
+
+    // Returns the size of the logical render area.  Layers are clipped to the
+    // logical render area.
+    virtual int getWidth() const = 0;
+    virtual int getHeight() const = 0;
+    virtual Rect getBounds() const = 0;
+
+    // Returns the source crop of the render area.  The source crop defines
+    // how layers are projected from the logical render area onto the physical
+    // render area.  It can be larger than the logical render area.  It can
+    // also be optionally rotated.
+    //
+    // Layers are first clipped to the source crop (in addition to being
+    // clipped to the logical render area already).  The source crop and the
+    // layers are then rotated around the center of the source crop, and
+    // scaled to the physical render area linearly.
+    virtual Rect getSourceCrop() const = 0;
+
+    // Returns the rotation of the source crop and the layers.
+    ui::Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
+
+    // Returns the size of the physical render area.
+    int getReqWidth() const { return mReqWidth; };
+    int getReqHeight() const { return mReqHeight; };
+
+    // Returns the fill color of the physical render area.  Regions not
+    // covered by any rendered layer should be filled with this color.
     CaptureFill getCaptureFill() const { return mCaptureFill; };
 
 private:
-    uint32_t mReqHeight;
-    uint32_t mReqWidth;
-    ui::Transform::orientation_flags mRotationFlags;
-    CaptureFill mCaptureFill;
+    const uint32_t mReqWidth;
+    const uint32_t mReqHeight;
+    const CaptureFill mCaptureFill;
+    const ui::Transform::orientation_flags mRotationFlags;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Android.bp b/services/surfaceflinger/RenderEngine/Android.bp
new file mode 100644
index 0000000..13752f2
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Android.bp
@@ -0,0 +1,75 @@
+// TODO(b/112585051) Add to VNDK once moved to libs/
+cc_defaults {
+    name: "renderengine_defaults",
+    cflags: [
+        "-DLOG_TAG=\"RenderEngine\"",
+        "-Wall",
+        "-Werror",
+        "-Wthread-safety",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+    cppflags: ["-std=c++1z"],
+}
+
+cc_defaults {
+    name: "librenderengine_defaults",
+    defaults: ["renderengine_defaults"],
+    cflags: [
+        "-DGL_GLEXT_PROTOTYPES",
+        "-DEGL_EGLEXT_PROTOTYPES",
+    ],
+    shared_libs: [
+        "android.hardware.configstore-utils",
+        "android.hardware.configstore@1.0",
+        "android.hardware.configstore@1.1",
+        "android.hardware.configstore@1.2",
+        "libcutils",
+        "libEGL",
+        "libGLESv1_CM",
+        "libGLESv2",
+        "libgui",
+        "liblog",
+        "libui",
+        "libutils",
+    ],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+}
+
+filegroup {
+    name: "librenderengine_sources",
+    srcs: [
+        "Description.cpp",
+        "GLES20RenderEngine.cpp",
+        "GLExtensions.cpp",
+        "Image.cpp",
+        "Mesh.cpp",
+        "Program.cpp",
+        "ProgramCache.cpp",
+        "RenderEngine.cpp",
+        "Surface.cpp",
+        "Texture.cpp",
+    ],
+}
+
+cc_library_static {
+    name: "librenderengine",
+    defaults: ["librenderengine_defaults"],
+    double_loadable: true,
+
+    clang: true,
+    cflags: [
+        "-fvisibility=hidden",
+        "-Werror=format",
+    ],
+    cppflags: [
+        "-fwhole-program-vtables", // requires ThinLTO
+    ],
+    srcs: [
+        ":librenderengine_sources",
+    ],
+    lto: {
+        thin: true,
+    },
+}
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index d4a2bb4..d5f2103 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
+#include <renderengine/Description.h>
+
 #include <stdint.h>
 #include <string.h>
 
 #include <utils/TypeHelpers.h>
 
-#include "Description.h"
-
 namespace android {
 
 void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 2186594..617ba76 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -19,26 +19,24 @@
 #define LOG_TAG "RenderEngine"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include <renderengine/GLES20RenderEngine.h>
+
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
-
+#include <renderengine/Description.h>
+#include <renderengine/Mesh.h>
+#include <renderengine/Program.h>
+#include <renderengine/ProgramCache.h>
+#include <renderengine/Texture.h>
 #include <ui/ColorSpace.h>
 #include <ui/DebugUtils.h>
 #include <ui/Rect.h>
-
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
 #include <cutils/compiler.h>
 #include <math.h>
 
-#include "Description.h"
-#include "GLES20RenderEngine.h"
-#include "Mesh.h"
-#include "Program.h"
-#include "ProgramCache.h"
-#include "Texture.h"
-
 #include <fstream>
 #include <sstream>
 
@@ -114,7 +112,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 +130,7 @@
 
     // mColorBlindnessCorrection = M;
 
-    if (mPlatformHasWideColor) {
+    if (mUseColorManagement) {
         ColorSpace srgb(ColorSpace::sRGB());
         ColorSpace displayP3(ColorSpace::DisplayP3());
         ColorSpace bt2020(ColorSpace::BT2020());
@@ -322,8 +320,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 +334,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 +368,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 +378,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/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp
index 23480b4..b4fb2a1 100644
--- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp
+++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
+#include <renderengine/GLExtensions.h>
+
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "GLExtensions.h"
-
 namespace android {
 // ---------------------------------------------------------------------------
 
diff --git a/services/surfaceflinger/RenderEngine/Image.cpp b/services/surfaceflinger/RenderEngine/Image.cpp
index 6e0a880..ee140eb 100644
--- a/services/surfaceflinger/RenderEngine/Image.cpp
+++ b/services/surfaceflinger/RenderEngine/Image.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#include "Image.h"
+#include <renderengine/Image.h>
 
 #include <vector>
 
 #include <log/log.h>
 
-#include "GLExtensions.h"
-#include "RenderEngine.h"
+#include <renderengine/GLExtensions.h>
+#include <renderengine/RenderEngine.h>
 
 namespace android {
 namespace RE {
diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp
index 6a62b1d..43852eb 100644
--- a/services/surfaceflinger/RenderEngine/Mesh.cpp
+++ b/services/surfaceflinger/RenderEngine/Mesh.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "Mesh.h"
+#include <renderengine/Mesh.h>
 
 #include <utils/Log.h>
 
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index fe536f0..87371dc 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
+#include <renderengine/Program.h>
+
 #include <stdint.h>
 
 #include <log/log.h>
-#include <utils/String8.h>
-
 #include <math/mat4.h>
-#include "Description.h"
-#include "Program.h"
-#include "ProgramCache.h"
+#include <renderengine/Description.h>
+#include <renderengine/ProgramCache.h>
+#include <utils/String8.h>
 
 namespace android {
 
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 9dc6858..b7101e0 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -16,16 +16,15 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include <renderengine/ProgramCache.h>
+
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
-
+#include <renderengine/Description.h>
+#include <renderengine/Program.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
-#include "Description.h"
-#include "Program.h"
-#include "ProgramCache.h"
-
 namespace android {
 // -----------------------------------------------------------------------------------------------
 
@@ -82,7 +81,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 +104,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/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 39f7e30..594b1ed 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -14,22 +14,21 @@
  * limitations under the License.
  */
 
-#include <log/log.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-
-#include "GLES20RenderEngine.h"
-#include "GLExtensions.h"
-#include "Image.h"
-#include "Mesh.h"
-#include "RenderEngine.h"
-
-#include <SurfaceFlinger.h>
-#include <vector>
+#include <renderengine/RenderEngine.h>
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
+#include <log/log.h>
 #include <private/gui/SyncFeatures.h>
+#include <renderengine/GLES20RenderEngine.h>
+#include <renderengine/GLExtensions.h>
+#include <renderengine/Image.h>
+#include <renderengine/Mesh.h>
+#include <renderengine/Surface.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include <vector>
 
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
@@ -596,7 +595,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/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp
index 3bf42fb..3e98ab4 100644
--- a/services/surfaceflinger/RenderEngine/Surface.cpp
+++ b/services/surfaceflinger/RenderEngine/Surface.cpp
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-#include "Surface.h"
-
-#include "RenderEngine.h"
+#include <renderengine/Surface.h>
 
 #include <log/log.h>
+#include <renderengine/RenderEngine.h>
 #include <ui/PixelFormat.h>
 
 namespace android {
diff --git a/services/surfaceflinger/RenderEngine/Texture.cpp b/services/surfaceflinger/RenderEngine/Texture.cpp
index 351430f..c07ba08 100644
--- a/services/surfaceflinger/RenderEngine/Texture.cpp
+++ b/services/surfaceflinger/RenderEngine/Texture.cpp
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#include <string.h>
+#include <renderengine/Texture.h>
 
-#include "Texture.h"
+#include <string.h>
 
 namespace android {
 
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/Description.h
similarity index 98%
rename from services/surfaceflinger/RenderEngine/Description.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/Description.h
index 6ebb340..9bc7e1c 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/Description.h
@@ -15,7 +15,7 @@
  */
 
 #include <GLES2/gl2.h>
-#include "Texture.h"
+#include <renderengine/Texture.h>
 
 #ifndef SF_RENDER_ENGINE_DESCRIPTION_H_
 #define SF_RENDER_ENGINE_DESCRIPTION_H_
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h
similarity index 92%
rename from services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h
index f682225..0e9efdb 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h
@@ -21,10 +21,9 @@
 #include <sys/types.h>
 
 #include <GLES2/gl2.h>
-
-#include "Description.h"
-#include "ProgramCache.h"
-#include "RenderEngine.h"
+#include <renderengine/Description.h>
+#include <renderengine/ProgramCache.h>
+#include <renderengine/RenderEngine.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -94,8 +93,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/GLExtensions.h b/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h
similarity index 99%
rename from services/surfaceflinger/RenderEngine/GLExtensions.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h
index a6a5053..1ff0d24 100644
--- a/services/surfaceflinger/RenderEngine/GLExtensions.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h
@@ -20,15 +20,15 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Singleton.h>
-#include <utils/SortedVector.h>
-#include <utils/String8.h>
-
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <utils/Singleton.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+
 namespace android {
 // ---------------------------------------------------------------------------
 
diff --git a/services/surfaceflinger/RenderEngine/Image.h b/services/surfaceflinger/RenderEngine/include/renderengine/Image.h
similarity index 100%
rename from services/surfaceflinger/RenderEngine/Image.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/Image.h
diff --git a/services/surfaceflinger/RenderEngine/Mesh.h b/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h
similarity index 100%
rename from services/surfaceflinger/RenderEngine/Mesh.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h
diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/include/renderengine/Program.h
similarity index 96%
rename from services/surfaceflinger/RenderEngine/Program.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/Program.h
index ae796c5..5e621cb 100644
--- a/services/surfaceflinger/RenderEngine/Program.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/Program.h
@@ -20,9 +20,8 @@
 #include <stdint.h>
 
 #include <GLES2/gl2.h>
-
-#include "Description.h"
-#include "ProgramCache.h"
+#include <renderengine/Description.h>
+#include <renderengine/ProgramCache.h>
 
 namespace android {
 
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h
similarity index 98%
rename from services/surfaceflinger/RenderEngine/ProgramCache.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h
index 983e7ba..a5bee45 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h
@@ -18,13 +18,11 @@
 #define SF_RENDER_ENGINE_PROGRAMCACHE_H
 
 #include <GLES2/gl2.h>
-
+#include <renderengine/Description.h>
 #include <utils/KeyedVector.h>
 #include <utils/Singleton.h>
 #include <utils/TypeHelpers.h>
 
-#include "Description.h"
-
 namespace android {
 
 class Description;
@@ -161,7 +159,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.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
similarity index 98%
rename from services/surfaceflinger/RenderEngine/RenderEngine.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
index 2ed2cc7..6213784 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
@@ -56,7 +56,7 @@
 class RenderEngine {
 public:
     enum FeatureFlag {
-        WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
+        USE_COLOR_MANAGEMENT = 1 << 0, // Device manages color
     };
 
     virtual ~RenderEngine() = 0;
diff --git a/services/surfaceflinger/RenderEngine/Surface.h b/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h
similarity index 100%
rename from services/surfaceflinger/RenderEngine/Surface.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/Surface.h
diff --git a/services/surfaceflinger/RenderEngine/Texture.h b/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h
similarity index 100%
rename from services/surfaceflinger/RenderEngine/Texture.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/Texture.h
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 9d9acd3..54a1b51 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -521,16 +521,18 @@
     mThread->updateModel(mPeriod, mPhase, mReferenceTime);
 }
 
-void DispSync::scalePeriod(uint32_t multiplier, uint32_t divisor) {
+void DispSync::scalePeriod(HWC2::Device::FrequencyScaler frequencyScaler) {
     Mutex::Autolock lock(mMutex);
 
     // if only 1 of the properties is updated, we will get to this
     // point "attempting" to set the scale to 1 when it is already
     // 1.  Check that special case so that we don't do a useless
     // update of the model.
-    if ((multiplier == 1) && (divisor == 1) && (mPeriod == mPeriodBase)) return;
+    if ((frequencyScaler.multiplier == 1) &&
+            (frequencyScaler.divisor == 1) &&
+            (mPeriod == mPeriodBase)) return;
 
-    mPeriod = mPeriodBase * multiplier / divisor;
+    mPeriod = mPeriodBase * frequencyScaler.multiplier / frequencyScaler.divisor;
     mThread->updateModel(mPeriod, mPhase, mReferenceTime);
 }
 
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index 183966f..b3aef2d 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -24,6 +24,7 @@
 #include <utils/Timers.h>
 
 #include <ui/FenceTime.h>
+#include <DisplayHardware/HWC2.h>
 
 #include <memory>
 
@@ -48,7 +49,7 @@
     virtual bool addResyncSample(nsecs_t timestamp) = 0;
     virtual void endResync() = 0;
     virtual void setPeriod(nsecs_t period) = 0;
-    virtual void scalePeriod(const uint32_t multiplier, uint32_t divisor) = 0;
+    virtual void scalePeriod(HWC2::Device::FrequencyScaler) = 0;
     virtual nsecs_t getPeriod() = 0;
     virtual void setRefreshSkipCount(int count) = 0;
     virtual status_t addEventListener(const char* name, nsecs_t phase, Callback* callback) = 0;
@@ -122,7 +123,7 @@
     // scale the vsync event model's period.   The function is added
     // for an experimental test mode and should not be used outside
     // of that purpose.
-    void scalePeriod(const uint32_t multiplier, uint32_t divisor);
+    void scalePeriod(HWC2::Device::FrequencyScaler frequencyScaler);
 
     // The getPeriod method returns the current vsync period.
     nsecs_t getPeriod() override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ae39202..5acfe59 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -47,7 +47,7 @@
 #include <gui/IDisplayEventConnection.h>
 #include <gui/LayerDebugInfo.h>
 #include <gui/Surface.h>
-
+#include <renderengine/RenderEngine.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
 #include <ui/UiConfig.h>
@@ -82,7 +82,6 @@
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/VirtualDisplaySurface.h"
 #include "Effects/Daltonizer.h"
-#include "RenderEngine/RenderEngine.h"
 #include "Scheduler/DispSync.h"
 #include "Scheduler/DispSyncSource.h"
 #include "Scheduler/EventControlThread.h"
@@ -91,8 +90,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>
 
@@ -141,6 +143,21 @@
     return false;
 }
 
+ui::Transform::orientation_flags fromSurfaceComposerRotation(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;
+}
+
 #pragma clang diagnostic pop
 
 class ConditionalLock {
@@ -176,6 +193,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 +277,6 @@
         mDebugDDMS(0),
         mDebugDisableHWC(0),
         mDebugDisableTransformHint(0),
-        mDebugInSwapBuffers(0),
-        mLastSwapBufferTime(0),
         mDebugInTransaction(0),
         mLastTransactionTime(0),
         mForceFullDamage(false),
@@ -304,6 +320,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 +617,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,
@@ -777,18 +794,18 @@
 
     // TODO: Not sure if display density should handled by SF any longer
     class Density {
-        static int getDensityFromProperty(char const* propName) {
+        static float getDensityFromProperty(char const* propName) {
             char property[PROPERTY_VALUE_MAX];
-            int density = 0;
+            float density = 0.0f;
             if (property_get(propName, property, nullptr) > 0) {
-                density = atoi(property);
+                density = strtof(property, nullptr);
             }
             return density;
         }
     public:
-        static int getEmuDensity() {
+        static float getEmuDensity() {
             return getDensityFromProperty("qemu.sf.lcd_density"); }
-        static int getBuildDensity()  {
+        static float getBuildDensity()  {
             return getDensityFromProperty("ro.sf.lcd_density"); }
     };
 
@@ -876,6 +893,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 +1467,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 +1494,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 +1580,7 @@
             layer->setPerFrameData(display);
         }
 
-        if (hasWideColorDisplay) {
+        if (useColorManagement) {
             ColorMode  colorMode;
             Dataspace dataSpace;
             RenderIntent renderIntent;
@@ -1542,46 +1590,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));
     }
 }
@@ -1945,80 +2003,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 +2126,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 +2240,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)) {
@@ -2895,22 +2946,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());
         }
     }
 
@@ -3896,6 +3942,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 +4180,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 +4206,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 +4279,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;
 
     /*
@@ -4280,6 +4357,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 +4391,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 +4404,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 +4516,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 +4552,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 +4785,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 +4819,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);
@@ -4766,27 +4844,45 @@
                 // Code 1029 is an experimental feature that allows applications to
                 // simulate a high frequency panel by setting a multiplier and divisor
                 // on the VSYNC-sf clock.  If either the multiplier or divisor are
-                // 0, then the code will set both to 1 to return the VSYNC-sf clock
-                // to it's normal frequency.
-                int multiplier = data.readInt32();
-                int divisor = data.readInt32();
+                // 0, then the code simply return the current multiplier and divisor.
+                HWC2::Device::FrequencyScaler frequencyScaler;
+                frequencyScaler.multiplier = data.readInt32();
+                frequencyScaler.divisor = data.readInt32();
 
-                if ((multiplier == 0) || (divisor == 0)) {
-                    multiplier = 1;
-                    divisor = 1;
+                if ((frequencyScaler.multiplier == 0) || (frequencyScaler.divisor == 0)) {
+                    frequencyScaler = getBE().mHwc->getDisplayFrequencyScaleParameters();
+                    reply->writeInt32(frequencyScaler.multiplier);
+                    reply->writeInt32(frequencyScaler.divisor);
+                    return NO_ERROR;
                 }
 
-                if ((multiplier == 1) && (divisor == 1)) {
+                if ((frequencyScaler.multiplier == 1) && (frequencyScaler.divisor == 1)) {
                     enableHardwareVsync();
                 } else {
                     disableHardwareVsync(true);
                 }
-                getBE().mHwc->getActiveConfig(DisplayDevice::DISPLAY_PRIMARY)
-                    ->scalePanelFrequency(multiplier, divisor);
-                mPrimaryDispSync->scalePeriod(multiplier, divisor);
+                mPrimaryDispSync->scalePeriod(frequencyScaler);
+                getBE().mHwc->setDisplayFrequencyScaleParameters(frequencyScaler);
 
-                ATRACE_INT("PeriodMultiplier", multiplier);
-                ATRACE_INT("PeriodDivisor", divisor);
+                ATRACE_INT("PeriodMultiplier", frequencyScaler.multiplier);
+                ATRACE_INT("PeriodDivisor", frequencyScaler.divisor);
+
+                const hwc2_display_t hwcDisplayId = getBE().mHwc->getActiveConfig(
+                        DisplayDevice::DISPLAY_PRIMARY)->getDisplayId();
+
+                onHotplugReceived(getBE().mComposerSequenceId,
+                        hwcDisplayId, HWC2::Connection::Disconnected);
+                onHotplugReceived(getBE().mComposerSequenceId,
+                        hwcDisplayId, HWC2::Connection::Connected);
+                frequencyScaler = getBE().mHwc->getDisplayFrequencyScaleParameters();
+                reply->writeInt32(frequencyScaler.multiplier);
+                reply->writeInt32(frequencyScaler.divisor);
+
+                return NO_ERROR;
+            }
+            // Is device color managed?
+            case 1030: {
+                reply->writeBool(useColorManagement);
                 return NO_ERROR;
             }
         }
@@ -4821,10 +4917,50 @@
 
     if (!displayToken) return BAD_VALUE;
 
-    const auto display = getDisplayDeviceLocked(displayToken);
-    if (!display) return BAD_VALUE;
+    auto renderAreaRotation = fromSurfaceComposerRotation(rotation);
 
-    DisplayRenderArea renderArea(display, sourceCrop, reqHeight, reqWidth, rotation);
+    sp<DisplayDevice> display;
+    {
+        Mutex::Autolock _l(mStateLock);
+
+        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());
+            }
+        }
+
+        // get screen geometry
+        uint32_t width = display->getWidth();
+        uint32_t height = display->getHeight();
+
+        if (renderAreaRotation & ui::Transform::ROT_90) {
+            std::swap(width, height);
+        }
+
+        if (mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
+            std::swap(width, height);
+        }
+
+        if ((reqWidth > width) || (reqHeight > height)) {
+            ALOGE("size mismatch (%d, %d) > (%d, %d)", reqWidth, reqHeight, width, height);
+        } else {
+            if (reqWidth == 0) {
+                reqWidth = width;
+            }
+            if (reqHeight == 0) {
+                reqHeight = height;
+            }
+        }
+    }
+
+    DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, renderAreaRotation);
 
     auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
                                     display, minLayerZ, maxLayerZ, std::placeholders::_1);
@@ -4840,7 +4976,7 @@
     public:
         LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop,
                         int32_t reqWidth, int32_t reqHeight, bool childrenOnly)
-              : RenderArea(reqHeight, reqWidth, CaptureFill::CLEAR),
+              : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR),
                 mLayer(layer),
                 mCrop(crop),
                 mFlinger(flinger),
@@ -4932,6 +5068,14 @@
     int32_t reqWidth = crop.width() * frameScale;
     int32_t reqHeight = crop.height() * frameScale;
 
+    // really small crop or frameScale
+    if (reqWidth <= 0) {
+        reqWidth = 1;
+    }
+    if (reqHeight <= 0) {
+        reqHeight = 1;
+    }
+
     LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, childrenOnly);
 
     auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) {
@@ -4953,8 +5097,6 @@
                                              bool useIdentityTransform) {
     ATRACE_CALL();
 
-    renderArea.updateDimensions(mPrimaryDisplayOrientation);
-
     const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
             GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
     *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(),
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/TimeStats/timestatsproto/timestats.proto b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
index ab7527e..b8f38c2 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
+++ b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
@@ -20,10 +20,11 @@
 
 option optimize_for = LITE_RUNTIME;
 
-// //depot/google3/java/com/google/android/apps/graphics/proto/timestats.proto
-// is based on this proto. Please only make valid protobuf changes to these
-// messages, and keep the other file in sync per Android release. Please also
-// do not include "option optimize_for = LITE_RUNTIME;" on google3 side.
+// //depot/google3/java/com/google/android/apps/graphics/stats/proto/
+// timestats.proto is based on this proto. Please only make valid protobuf
+// changes to these messages, and keep the other file in sync per Android
+// release. Please also do not include "option optimize_for = LITE_RUNTIME;" at
+// google3 side.
 
 // Next tag: 7
 message SFTimeStatsGlobalProto {
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/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 6ad1b87..a5b522e 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -30,8 +30,9 @@
         "libutils",
     ],
     static_libs: [
+        "libgmock",
+        "librenderengine",
         "libtrace_proto",
-        "libgmock"
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
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/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index 06a6b69..46d6558 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -35,7 +35,7 @@
     MOCK_METHOD1(addResyncSample, bool(nsecs_t));
     MOCK_METHOD0(endResync, void());
     MOCK_METHOD1(setPeriod, void(nsecs_t));
-    MOCK_METHOD2(scalePeriod, void(uint32_t, uint32_t));
+    MOCK_METHOD1(scalePeriod, void(HWC2::Device::FrequencyScaler));
     MOCK_METHOD0(getPeriod, nsecs_t());
     MOCK_METHOD1(setRefreshSkipCount, void(int));
     MOCK_METHOD3(addEventListener, status_t(const char*, nsecs_t, Callback*));
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 36f74b6..b907c49 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -18,11 +18,11 @@
 
 #include <gmock/gmock.h>
 
-#include "RenderEngine/Image.h"
-#include "RenderEngine/Mesh.h"
-#include "RenderEngine/RenderEngine.h"
-#include "RenderEngine/Surface.h"
-#include "RenderEngine/Texture.h"
+#include <renderengine/Image.h>
+#include <renderengine/Mesh.h>
+#include <renderengine/RenderEngine.h>
+#include <renderengine/Surface.h>
+#include <renderengine/Texture.h>
 
 namespace android {
 namespace RE {
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index d1ed12b..417460c 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -332,10 +332,14 @@
   return Error::NONE;
 }
 
-Error VrHwc::getClientTargetSupport(Display /* display */, uint32_t /* width */,
+Error VrHwc::getClientTargetSupport(Display display, uint32_t /* width */,
                                     uint32_t /* height */,
                                     PixelFormat /* format */,
                                     Dataspace /* dataspace */) {
+  std::lock_guard<std::mutex> guard(mutex_);
+  if (!FindDisplay(display))
+    return Error::BAD_DISPLAY;
+
   return Error::NONE;
 }
 
@@ -466,16 +470,37 @@
   if (!display_ptr)
     return Error::BAD_DISPLAY;
 
+  if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_P3)
+    return Error::BAD_PARAMETER;
+
   display_ptr->set_color_mode(mode);
   return Error::NONE;
 }
 
 Error VrHwc::setPowerMode(Display display, IComposerClient::PowerMode mode) {
+  bool dozeSupported = false;
+
+  Error dozeSupportError = getDozeSupport(display, &dozeSupported);
+
+  if (dozeSupportError != Error::NONE)
+    return dozeSupportError;
+
   std::lock_guard<std::mutex> guard(mutex_);
   auto display_ptr = FindDisplay(display);
   if (!display_ptr)
     return Error::BAD_DISPLAY;
 
+  if (mode < IComposerClient::PowerMode::OFF ||
+      mode > IComposerClient::PowerMode::DOZE_SUSPEND) {
+    return Error::BAD_PARAMETER;
+  }
+
+  if (!dozeSupported &&
+      (mode == IComposerClient::PowerMode::DOZE ||
+       mode == IComposerClient::PowerMode::DOZE_SUSPEND)) {
+    return Error::UNSUPPORTED;
+  }
+
   display_ptr->set_power_mode(mode);
   return Error::NONE;
 }