Merge "surfaceflinger: fix misplacement of getHwComposer related function"
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
index 75855cf..ded0ed3 100644
--- a/cmds/bugreportz/bugreportz.cpp
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -55,7 +55,7 @@
                 errno = ETIMEDOUT;
             }
             printf("FAIL:Bugreport read terminated abnormally (%s)\n", strerror(errno));
-            break;
+            return EXIT_FAILURE;
         }
 
         // Writes line by line.
@@ -71,8 +71,5 @@
     // Process final line, in case it didn't finish with newline
     write_line(line, show_progress);
 
-    if (close(s) == -1) {
-        fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno));
-    }
     return EXIT_SUCCESS;
 }
diff --git a/cmds/bugreportz/bugreportz.h b/cmds/bugreportz/bugreportz.h
index 304e4b3..7af289b 100644
--- a/cmds/bugreportz/bugreportz.h
+++ b/cmds/bugreportz/bugreportz.h
@@ -16,6 +16,7 @@
 #define BUGREPORTZ_H
 
 // Calls dumpstate using the given socket and output its result to stdout.
+// Ownership of the socket is not transferred.
 int bugreportz(int s, bool show_progress);
 
 #endif  // BUGREPORTZ_H
diff --git a/cmds/bugreportz/main.cpp b/cmds/bugreportz/main.cpp
index a3ae1ff..74a95b0 100644
--- a/cmds/bugreportz/main.cpp
+++ b/cmds/bugreportz/main.cpp
@@ -82,7 +82,7 @@
 
     if (s == -1) {
         printf("FAIL:Failed to connect to dumpstatez service: %s\n", strerror(errno));
-        return EXIT_SUCCESS;
+        return EXIT_FAILURE;
     }
 
     // Set a timeout so that if nothing is read in 10 minutes, we'll stop
@@ -92,8 +92,16 @@
     tv.tv_sec = 10 * 60;
     tv.tv_usec = 0;
     if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
-        fprintf(stderr, "WARNING: Cannot set socket timeout: %s\n", strerror(errno));
+        fprintf(stderr,
+                "WARNING: Cannot set socket timeout, bugreportz might hang indefinitely: %s\n",
+                strerror(errno));
     }
 
-    bugreportz(s, show_progress);
+    int ret = bugreportz(s, show_progress);
+
+    if (close(s) == -1) {
+        fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno));
+        ret = EXIT_FAILURE;
+    }
+    return ret;
 }
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 8b2f842..0d224d8 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -46,6 +46,7 @@
         "android.hardware.bluetooth@1.0::IBluetoothHci",
         "android.hardware.camera.provider@2.4::ICameraProvider",
         "android.hardware.drm@1.0::IDrmFactory",
+        "android.hardware.graphics.allocator@2.0::IAllocator",
         "android.hardware.graphics.composer@2.1::IComposer",
         "android.hardware.media.omx@1.0::IOmx",
         "android.hardware.media.omx@1.0::IOmxStore",
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e401572..98ec338 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -220,12 +220,12 @@
 
 class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
 public:
-    enum {
+    enum ISurfaceComposerTag {
         // Note: BOOT_FINISHED must remain this value, it is called from
         // Java by ActivityManagerService.
         BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
         CREATE_CONNECTION,
-        UNUSED, // formerly CREATE_GRAPHIC_BUFFER_ALLOC
+        CREATE_GRAPHIC_BUFFER_ALLOC_UNUSED, // unused, fails permissions check
         CREATE_DISPLAY_EVENT_CONNECTION,
         CREATE_DISPLAY,
         DESTROY_DISPLAY,
@@ -236,7 +236,7 @@
         GET_DISPLAY_CONFIGS,
         GET_ACTIVE_CONFIG,
         SET_ACTIVE_CONFIG,
-        CONNECT_DISPLAY,
+        CONNECT_DISPLAY_UNUSED, // unused, fails permissions check
         CAPTURE_SCREEN,
         CAPTURE_LAYERS,
         CLEAR_ANIMATION_FRAME_STATS,
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 863e426..c805805 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -515,10 +515,9 @@
 sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
         int32_t x, int32_t y) {
     // Traverse windows from front to back to find touched window.
-    const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
-    size_t numWindows = windowHandles.size();
+    size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
+        sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
         const InputWindowInfo* windowInfo = windowHandle->getInfo();
         if (windowInfo->displayId == displayId) {
             int32_t flags = windowInfo->layoutParamsFlags;
@@ -1248,10 +1247,9 @@
         bool isTouchModal = false;
 
         // Traverse windows from front to back to find touched window and outside targets.
-        const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
-        size_t numWindows = windowHandles.size();
+        size_t numWindows = mWindowHandles.size();
         for (size_t i = 0; i < numWindows; i++) {
-            sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
+            sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
             const InputWindowInfo* windowInfo = windowHandle->getInfo();
             if (windowInfo->displayId != displayId) {
                 continue; // wrong display
@@ -1474,10 +1472,8 @@
         sp<InputWindowHandle> foregroundWindowHandle =
                 mTempTouchState.getFirstForegroundWindowHandle();
         if (foregroundWindowHandle->getInfo()->hasWallpaper) {
-            const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
-            size_t numWindows = windowHandles.size();
-            for (size_t i = 0; i < numWindows; i++) {
-                sp<InputWindowHandle> windowHandle = windowHandles.itemAt(i);
+            for (size_t i = 0; i < mWindowHandles.size(); i++) {
+                sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
                 const InputWindowInfo* info = windowHandle->getInfo();
                 if (info->displayId == displayId
                         && windowHandle->getInfo()->layoutParamsType
@@ -1662,10 +1658,9 @@
 bool InputDispatcher::isWindowObscuredAtPointLocked(
         const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
     int32_t displayId = windowHandle->getInfo()->displayId;
-    const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
-    size_t numWindows = windowHandles.size();
+    size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        sp<InputWindowHandle> otherHandle = windowHandles.itemAt(i);
+        sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
         if (otherHandle == windowHandle) {
             break;
         }
@@ -1683,11 +1678,10 @@
 
 bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
     int32_t displayId = windowHandle->getInfo()->displayId;
-    const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
     const InputWindowInfo* windowInfo = windowHandle->getInfo();
-    size_t numWindows = windowHandles.size();
+    size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        sp<InputWindowHandle> otherHandle = windowHandles.itemAt(i);
+        sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
         if (otherHandle == windowHandle) {
             break;
         }
@@ -2915,77 +2909,52 @@
     }
 }
 
-Vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(int32_t displayId) const {
-    std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>>::const_iterator it
-        = mWindowHandlesByDisplay.find(displayId);
-    if(it != mWindowHandlesByDisplay.end()) {
-        return it->second;
-    }
-
-    // Return an empty one if nothing found.
-    return Vector<sp<InputWindowHandle>>();
-}
-
 sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
         const sp<InputChannel>& inputChannel) const {
-    for (auto& it : mWindowHandlesByDisplay) {
-        const Vector<sp<InputWindowHandle>> windowHandles = it.second;
-        size_t numWindows = windowHandles.size();
-        for (size_t i = 0; i < numWindows; i++) {
-            const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
-            if (windowHandle->getInputChannel() == inputChannel) {
-                return windowHandle;
-            }
+    size_t numWindows = mWindowHandles.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+        if (windowHandle->getInputChannel() == inputChannel) {
+            return windowHandle;
         }
     }
     return nullptr;
 }
 
 bool InputDispatcher::hasWindowHandleLocked(
-        const sp<InputWindowHandle>& windowHandle, int32_t displayId) const {
-
-    const Vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
-    size_t numWindows = windowHandles.size();
+        const sp<InputWindowHandle>& windowHandle) const {
+    size_t numWindows = mWindowHandles.size();
     for (size_t i = 0; i < numWindows; i++) {
-        if (windowHandles.itemAt(i) == windowHandle) {
+        if (mWindowHandles.itemAt(i) == windowHandle) {
             return true;
         }
     }
     return false;
 }
 
-void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& inputWindowHandles,
-        int displayId) {
+void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
 #if DEBUG_FOCUS
     ALOGD("setInputWindows");
 #endif
     { // acquire lock
         AutoMutex _l(mLock);
 
-        const Vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
-        Vector<sp<InputWindowHandle>> windowHandles = inputWindowHandles;
-        // Insert or replace
-        mWindowHandlesByDisplay[displayId] = windowHandles;
+        Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
+        mWindowHandles = inputWindowHandles;
 
-        // TODO(b/111361570): multi-display focus, one focus in all display in current.
-        sp<InputWindowHandle> newFocusedWindowHandle = mFocusedWindowHandle;
+        sp<InputWindowHandle> newFocusedWindowHandle;
         bool foundHoveredWindow = false;
-
-        if (windowHandles.isEmpty()) {
-            // Remove all handles on a display if there are no windows left.
-            mWindowHandlesByDisplay.erase(displayId);
-        } else {
-            for (size_t i = 0; i < windowHandles.size(); i++) {
-                const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
-                if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == nullptr) {
-                    continue;
-                }
-                if (windowHandle->getInfo()->hasFocus) {
-                    newFocusedWindowHandle = windowHandle;
-                }
-                if (windowHandle == mLastHoverWindowHandle) {
-                    foundHoveredWindow = true;
-                }
+        for (size_t i = 0; i < mWindowHandles.size(); i++) {
+            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+            if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == nullptr) {
+                mWindowHandles.removeAt(i--);
+                continue;
+            }
+            if (windowHandle->getInfo()->hasFocus) {
+                newFocusedWindowHandle = windowHandle;
+            }
+            if (windowHandle == mLastHoverWindowHandle) {
+                foundHoveredWindow = true;
             }
         }
 
@@ -2993,7 +2962,6 @@
             mLastHoverWindowHandle = nullptr;
         }
 
-        // TODO(b/111361570): multi-display focus, one focus in all display in current.
         if (mFocusedWindowHandle != newFocusedWindowHandle) {
             if (mFocusedWindowHandle != nullptr) {
 #if DEBUG_FOCUS
@@ -3017,12 +2985,11 @@
             mFocusedWindowHandle = newFocusedWindowHandle;
         }
 
-        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
-        if (stateIndex >= 0) {
-            TouchState& state = mTouchStatesByDisplay.editValueAt(stateIndex);
+        for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
+            TouchState& state = mTouchStatesByDisplay.editValueAt(d);
             for (size_t i = 0; i < state.windows.size(); ) {
                 TouchedWindow& touchedWindow = state.windows.editItemAt(i);
-                if (!hasWindowHandleLocked(touchedWindow.windowHandle, displayId)) {
+                if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
 #if DEBUG_FOCUS
                     ALOGD("Touched window was removed: %s",
                             touchedWindow.windowHandle->getName().c_str());
@@ -3048,7 +3015,7 @@
         // which might not happen until the next GC.
         for (size_t i = 0; i < oldWindowHandles.size(); i++) {
             const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i);
-            if (!hasWindowHandleLocked(oldWindowHandle, displayId)) {
+            if (!hasWindowHandleLocked(oldWindowHandle)) {
 #if DEBUG_FOCUS
                 ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
 #endif
@@ -3299,44 +3266,36 @@
         dump += INDENT "TouchStates: <no displays touched>\n";
     }
 
-    if (!mWindowHandlesByDisplay.empty()) {
-       for (auto& it : mWindowHandlesByDisplay) {
-            const Vector<sp<InputWindowHandle>> windowHandles = it.second;
-            dump += StringPrintf(INDENT "Display: %d\n", it.first);
-            if (!windowHandles.isEmpty()) {
-                dump += INDENT "Windows:\n";
-                for (size_t i = 0; i < windowHandles.size(); i++) {
-                    const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
-                    const InputWindowInfo* windowInfo = windowHandle->getInfo();
+    if (!mWindowHandles.isEmpty()) {
+        dump += INDENT "Windows:\n";
+        for (size_t i = 0; i < mWindowHandles.size(); i++) {
+            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
+            const InputWindowInfo* windowInfo = windowHandle->getInfo();
 
-                    dump += StringPrintf(INDENT2 "%zu: name='%s', displayId=%d, "
-                            "paused=%s, hasFocus=%s, hasWallpaper=%s, "
-                            "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
-                            "frame=[%d,%d][%d,%d], scale=%f, "
-                            "touchableRegion=",
-                            i, windowInfo->name.c_str(), windowInfo->displayId,
-                            toString(windowInfo->paused),
-                            toString(windowInfo->hasFocus),
-                            toString(windowInfo->hasWallpaper),
-                            toString(windowInfo->visible),
-                            toString(windowInfo->canReceiveKeys),
-                            windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
-                            windowInfo->layer,
-                            windowInfo->frameLeft, windowInfo->frameTop,
-                            windowInfo->frameRight, windowInfo->frameBottom,
-                            windowInfo->scaleFactor);
-                    dumpRegion(dump, windowInfo->touchableRegion);
-                    dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
-                    dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
-                            windowInfo->ownerPid, windowInfo->ownerUid,
-                            windowInfo->dispatchingTimeout / 1000000.0);
-                }
-            } else {
-                dump += INDENT "Windows: <none>\n";
-            }
+            dump += StringPrintf(INDENT2 "%zu: name='%s', displayId=%d, "
+                    "paused=%s, hasFocus=%s, hasWallpaper=%s, "
+                    "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
+                    "frame=[%d,%d][%d,%d], scale=%f, "
+                    "touchableRegion=",
+                    i, windowInfo->name.c_str(), windowInfo->displayId,
+                    toString(windowInfo->paused),
+                    toString(windowInfo->hasFocus),
+                    toString(windowInfo->hasWallpaper),
+                    toString(windowInfo->visible),
+                    toString(windowInfo->canReceiveKeys),
+                    windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
+                    windowInfo->layer,
+                    windowInfo->frameLeft, windowInfo->frameTop,
+                    windowInfo->frameRight, windowInfo->frameBottom,
+                    windowInfo->scaleFactor);
+            dumpRegion(dump, windowInfo->touchableRegion);
+            dump += StringPrintf(", inputFeatures=0x%08x", windowInfo->inputFeatures);
+            dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
+                    windowInfo->ownerPid, windowInfo->ownerUid,
+                    windowInfo->dispatchingTimeout / 1000000.0);
         }
     } else {
-        dump += INDENT "Displays: <none>\n";
+        dump += INDENT "Windows: <none>\n";
     }
 
     if (!mMonitoringChannels.isEmpty()) {
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 5cb7fe1..31ab339 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -31,7 +31,6 @@
 #include <stddef.h>
 #include <unistd.h>
 #include <limits.h>
-#include <unordered_map>
 
 #include "InputWindow.h"
 #include "InputApplication.h"
@@ -308,8 +307,7 @@
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
-            int displayId) = 0;
+    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
 
     /* Sets the focused application.
      *
@@ -389,8 +387,7 @@
             int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
             uint32_t policyFlags);
 
-    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
-            int displayId);
+    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
     virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
     virtual void setInputDispatchMode(bool enabled, bool frozen);
     virtual void setInputFilterEnabled(bool enabled);
@@ -959,11 +956,10 @@
     bool mDispatchFrozen;
     bool mInputFilterEnabled;
 
-    std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay;
-    // Get window handles by display, return an empty vector if not found.
-    Vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const;
+    Vector<sp<InputWindowHandle> > mWindowHandles;
+
     sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
-    bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle, int32_t displayId) const;
+    bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
 
     // Focus tracking for keys, trackball, etc.
     sp<InputWindowHandle> mFocusedWindowHandle;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index d0aa742..fa0141f 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -128,6 +128,7 @@
         "RenderEngine/Surface.cpp",
         "RenderEngine/Texture.cpp",
         "Scheduler/DispSync.cpp",
+        "Scheduler/DispSyncSource.cpp",
         "Scheduler/EventControlThread.cpp",
         "Scheduler/EventThread.cpp",
         "Scheduler/MessageQueue.cpp",
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ee9ee78..fef53bb 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -230,7 +230,10 @@
 bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) {
     LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0,
                         "Already have a layer for display %d", displayId);
-    HWC2::Layer* layer = hwc->createLayer(displayId);
+    auto layer = std::shared_ptr<HWC2::Layer>(
+            hwc->createLayer(displayId),
+            [hwc, displayId](HWC2::Layer* layer) {
+               hwc->destroyLayer(displayId, layer); });
     if (!layer) {
         return false;
     }
@@ -249,11 +252,8 @@
     auto& hwcInfo = getBE().mHwcLayers[displayId];
     LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
     LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
-    hwcInfo.hwc->destroyLayer(displayId, hwcInfo.layer);
-    // The layer destroyed listener should have cleared the entry from
-    // mHwcLayers. Verify that.
-    LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0,
-                        "Stale layer entry in getBE().mHwcLayers");
+    hwcInfo.layer = nullptr;
+
     return true;
 }
 
@@ -716,7 +716,8 @@
     auto position = displayTransform.transform(frame);
 
     auto error =
-            getBE().mHwcLayers[displayId].layer->setCursorPosition(position.left, position.top);
+            (getBE().mHwcLayers[displayId].layer)->setCursorPosition(
+                    position.left, position.top);
     ALOGE_IF(error != HWC2::Error::None,
              "[%s] Failed to set cursor position "
              "to (%d, %d): %s (%d)",
@@ -759,13 +760,13 @@
     }
     auto& hwcInfo = getBE().mHwcLayers[displayId];
     auto& hwcLayer = hwcInfo.layer;
-    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
+    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (hwcLayer)->getId(), to_string(type).c_str(),
           static_cast<int>(callIntoHwc));
     if (hwcInfo.compositionType != type) {
         ALOGV("    actually setting");
         hwcInfo.compositionType = type;
         if (callIntoHwc) {
-            auto error = hwcLayer->setCompositionType(type);
+            auto error = (hwcLayer)->setCompositionType(type);
             ALOGE_IF(error != HWC2::Error::None,
                      "[%s] Failed to set "
                      "composition type %s: %s (%d)",
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a48cdff..a6da495 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -510,7 +510,7 @@
         if (getBE().mHwcLayers.count(displayId) == 0) {
             return nullptr;
         }
-        return getBE().mHwcLayers[displayId].layer;
+        return getBE().mHwcLayers[displayId].layer.get();
     }
 
     // -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index 51b615b..b936b3f 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -26,16 +26,23 @@
 LayerBE::LayerBE(Layer* layer, std::string layerName)
       : mLayer(layer),
         mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
-    compositionInfo.layer = this;
+    compositionInfo.layer = std::make_shared<LayerBE>(*this);
     compositionInfo.layerName = layerName;
 }
 
+LayerBE::LayerBE(const LayerBE& layer)
+      : mLayer(layer.mLayer),
+        mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
+    compositionInfo.layer = layer.compositionInfo.layer;
+    compositionInfo.layerName = layer.mLayer->getName().string();
+}
+
 void LayerBE::onLayerDisplayed(const sp<Fence>& releaseFence) {
     mLayer->onLayerDisplayed(releaseFence);
 }
 
 void CompositionInfo::dumpHwc(const char* tag) const {
-    ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer);
+    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);
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index b5aceba..3055621 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -37,9 +37,9 @@
     HWC2::Composition compositionType;
     sp<GraphicBuffer> mBuffer = nullptr;
     int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
-    LayerBE* layer = nullptr;
+    std::shared_ptr<LayerBE> layer;
     struct {
-        HWC2::Layer* hwcLayer;
+        std::shared_ptr<HWC2::Layer> hwcLayer;
         sp<Fence> fence;
         HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid;
         Rect displayFrame;
@@ -54,6 +54,7 @@
         sp<NativeHandle> sidebandStream;
         ui::Dataspace dataspace;
         hwc_color_t color;
+        bool clearClientTarget = false;
     } hwc;
     struct {
         Mesh* mesh;
@@ -83,6 +84,7 @@
     friend class SurfaceFlinger;
 
     LayerBE(Layer* layer, std::string layerName);
+    explicit LayerBE(const LayerBE& layer);
 
     void onLayerDisplayed(const sp<Fence>& releaseFence);
     Mesh& getMesh() { return mMesh; }
@@ -103,7 +105,7 @@
                 transform(HWC2::Transform::None) {}
 
         HWComposer* hwc;
-        HWC2::Layer* layer;
+        std::shared_ptr<HWC2::Layer> layer;
         bool forceClientComposition;
         HWC2::Composition compositionType;
         bool clearClientTarget;
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
new file mode 100644
index 0000000..61f2ac8
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DispSyncSource.h"
+
+#include <android-base/stringprintf.h>
+#include <utils/Trace.h>
+#include <mutex>
+
+#include "DispSync.h"
+#include "EventThread.h"
+
+namespace android {
+
+DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
+                               const char* name)
+      : mName(name),
+        mTraceVsync(traceVsync),
+        mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
+        mVsyncEventLabel(base::StringPrintf("VSYNC-%s", name)),
+        mDispSync(dispSync),
+        mPhaseOffset(phaseOffset) {}
+
+void DispSyncSource::setVSyncEnabled(bool enable) {
+    std::lock_guard lock(mVsyncMutex);
+    if (enable) {
+        status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
+                                                   static_cast<DispSync::Callback*>(this));
+        if (err != NO_ERROR) {
+            ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err);
+        }
+        // ATRACE_INT(mVsyncOnLabel.c_str(), 1);
+    } else {
+        status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));
+        if (err != NO_ERROR) {
+            ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err);
+        }
+        // ATRACE_INT(mVsyncOnLabel.c_str(), 0);
+    }
+    mEnabled = enable;
+}
+
+void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
+    std::lock_guard lock(mCallbackMutex);
+    mCallback = callback;
+}
+
+void DispSyncSource::setPhaseOffset(nsecs_t phaseOffset) {
+    std::lock_guard lock(mVsyncMutex);
+
+    // Normalize phaseOffset to [0, period)
+    auto period = mDispSync->getPeriod();
+    phaseOffset %= period;
+    if (phaseOffset < 0) {
+        // If we're here, then phaseOffset is in (-period, 0). After this
+        // operation, it will be in (0, period)
+        phaseOffset += period;
+    }
+    mPhaseOffset = phaseOffset;
+
+    // If we're not enabled, we don't need to mess with the listeners
+    if (!mEnabled) {
+        return;
+    }
+
+    status_t err =
+            mDispSync->changePhaseOffset(static_cast<DispSync::Callback*>(this), mPhaseOffset);
+    if (err != NO_ERROR) {
+        ALOGE("error changing vsync offset: %s (%d)", strerror(-err), err);
+    }
+}
+
+void DispSyncSource::onDispSyncEvent(nsecs_t when) {
+    VSyncSource::Callback* callback;
+    {
+        std::lock_guard lock(mCallbackMutex);
+        callback = mCallback;
+
+        if (mTraceVsync) {
+            mValue = (mValue + 1) % 2;
+            ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
+        }
+    }
+
+    if (callback != nullptr) {
+        callback->onVSyncEvent(when);
+    }
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
new file mode 100644
index 0000000..0fd84a2
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <mutex>
+#include <string>
+
+#include "DispSync.h"
+#include "EventThread.h"
+
+namespace android {
+
+class DispSyncSource final : public VSyncSource, private DispSync::Callback {
+public:
+    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name);
+
+    ~DispSyncSource() override = default;
+
+    // The following methods are implementation of VSyncSource.
+    void setVSyncEnabled(bool enable) override;
+    void setCallback(VSyncSource::Callback* callback) override;
+    void setPhaseOffset(nsecs_t phaseOffset) override;
+
+private:
+    // The following method is the implementation of the DispSync::Callback.
+    virtual void onDispSyncEvent(nsecs_t when);
+
+    const char* const mName;
+    int mValue = 0;
+
+    const bool mTraceVsync;
+    const std::string mVsyncOnLabel;
+    const std::string mVsyncEventLabel;
+
+    DispSync* mDispSync;
+
+    std::mutex mCallbackMutex;
+    VSyncSource::Callback* mCallback GUARDED_BY(mCallbackMutex) = nullptr;
+
+    std::mutex mVsyncMutex;
+    nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
+    bool mEnabled GUARDED_BY(mVsyncMutex) = false;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1b0064f..8ef15bd 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -85,6 +85,7 @@
 #include "Effects/Daltonizer.h"
 #include "RenderEngine/RenderEngine.h"
 #include "Scheduler/DispSync.h"
+#include "Scheduler/DispSyncSource.h"
 #include "Scheduler/EventControlThread.h"
 #include "Scheduler/EventThread.h"
 
@@ -265,6 +266,7 @@
         mForceFullDamage(false),
         mPrimaryHWVsyncEnabled(false),
         mHWVsyncAvailable(false),
+        mRefreshStartTime(0),
         mHasPoweredOff(false),
         mNumLayers(0),
         mVrFlingerRequestsDisplay(false),
@@ -564,112 +566,6 @@
     postMessageAsync(new LambdaMessage([=] { getRenderEngine().deleteTextures(1, &texture); }));
 }
 
-class DispSyncSource final : public VSyncSource, private DispSync::Callback {
-public:
-    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
-        const char* name) :
-            mName(name),
-            mValue(0),
-            mTraceVsync(traceVsync),
-            mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
-            mVsyncEventLabel(String8::format("VSYNC-%s", name)),
-            mDispSync(dispSync),
-            mCallbackMutex(),
-            mVsyncMutex(),
-            mPhaseOffset(phaseOffset),
-            mEnabled(false) {}
-
-    ~DispSyncSource() override = default;
-
-    void setVSyncEnabled(bool enable) override {
-        Mutex::Autolock lock(mVsyncMutex);
-        if (enable) {
-            status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
-                    static_cast<DispSync::Callback*>(this));
-            if (err != NO_ERROR) {
-                ALOGE("error registering vsync callback: %s (%d)",
-                        strerror(-err), err);
-            }
-            //ATRACE_INT(mVsyncOnLabel.string(), 1);
-        } else {
-            status_t err = mDispSync->removeEventListener(
-                    static_cast<DispSync::Callback*>(this));
-            if (err != NO_ERROR) {
-                ALOGE("error unregistering vsync callback: %s (%d)",
-                        strerror(-err), err);
-            }
-            //ATRACE_INT(mVsyncOnLabel.string(), 0);
-        }
-        mEnabled = enable;
-    }
-
-    void setCallback(VSyncSource::Callback* callback) override{
-        Mutex::Autolock lock(mCallbackMutex);
-        mCallback = callback;
-    }
-
-    void setPhaseOffset(nsecs_t phaseOffset) override {
-        Mutex::Autolock lock(mVsyncMutex);
-
-        // Normalize phaseOffset to [0, period)
-        auto period = mDispSync->getPeriod();
-        phaseOffset %= period;
-        if (phaseOffset < 0) {
-            // If we're here, then phaseOffset is in (-period, 0). After this
-            // operation, it will be in (0, period)
-            phaseOffset += period;
-        }
-        mPhaseOffset = phaseOffset;
-
-        // If we're not enabled, we don't need to mess with the listeners
-        if (!mEnabled) {
-            return;
-        }
-
-        status_t err = mDispSync->changePhaseOffset(static_cast<DispSync::Callback*>(this),
-                mPhaseOffset);
-        if (err != NO_ERROR) {
-            ALOGE("error changing vsync offset: %s (%d)",
-                    strerror(-err), err);
-        }
-    }
-
-private:
-    virtual void onDispSyncEvent(nsecs_t when) {
-        VSyncSource::Callback* callback;
-        {
-            Mutex::Autolock lock(mCallbackMutex);
-            callback = mCallback;
-
-            if (mTraceVsync) {
-                mValue = (mValue + 1) % 2;
-                ATRACE_INT(mVsyncEventLabel.string(), mValue);
-            }
-        }
-
-        if (callback != nullptr) {
-            callback->onVSyncEvent(when);
-        }
-    }
-
-    const char* const mName;
-
-    int mValue;
-
-    const bool mTraceVsync;
-    const String8 mVsyncOnLabel;
-    const String8 mVsyncEventLabel;
-
-    DispSync* mDispSync;
-
-    Mutex mCallbackMutex; // Protects the following
-    VSyncSource::Callback* mCallback = nullptr;
-
-    Mutex mVsyncMutex; // Protects the following
-    nsecs_t mPhaseOffset;
-    bool mEnabled;
-};
-
 class InjectVSyncSource final : public VSyncSource {
 public:
     InjectVSyncSource() = default;
@@ -1220,15 +1116,6 @@
 
 status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const
         NO_THREAD_SAFETY_ANALYSIS {
-    IPCThreadState* ipc = IPCThreadState::self();
-    const int pid = ipc->getCallingPid();
-    const int uid = ipc->getCallingUid();
-    if ((uid != AID_SHELL) &&
-            !PermissionCache::checkPermission(sDump, pid, uid)) {
-        ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
-        return PERMISSION_DENIED;
-    }
-
     // Try to acquire a lock for 1s, fail gracefully
     const status_t err = mStateLock.timedLock(s2ns(1));
     const bool locked = (err == NO_ERROR);
@@ -1583,16 +1470,16 @@
 
     mRefreshPending = false;
 
-    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    preComposition(refreshStartTime);
+    preComposition();
     rebuildLayerStacks();
-    setUpHWComposer();
+    calculateWorkingSet();
+    beginFrame();
+    prepareFrame();
     doDebugFlashRegions();
     doTracing("handleRefresh");
     logLayerStats();
     doComposition();
-    postComposition(refreshStartTime);
+    postComposition();
 
     mHadClientComposition = false;
     for (const auto& [token, display] : mDisplays) {
@@ -1604,6 +1491,84 @@
     mLayersWithQueuedFrames.clear();
 }
 
+void SurfaceFlinger::calculateWorkingSet() {
+    ATRACE_CALL();
+    ALOGV(__FUNCTION__);
+
+    // build the h/w work list
+    if (CC_UNLIKELY(mGeometryInvalid)) {
+        mGeometryInvalid = false;
+        for (const auto& [token, display] : mDisplays) {
+            const auto displayId = display->getId();
+            if (displayId >= 0) {
+                const Vector<sp<Layer>>& currentLayers(
+                        display->getVisibleLayersSortedByZ());
+                for (size_t i = 0; i < currentLayers.size(); i++) {
+                    const auto& layer = currentLayers[i];
+
+                    if (!layer->hasHwcLayer(displayId)) {
+                        if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) {
+                            layer->forceClientComposition(displayId);
+                            continue;
+                        }
+                    }
+
+                    layer->setGeometry(display, i);
+                    if (mDebugDisableHWC || mDebugRegion) {
+                        layer->forceClientComposition(displayId);
+                    }
+                }
+            }
+        }
+    }
+
+    // Set the per-frame data
+    for (const auto& [token, display] : mDisplays) {
+        const auto displayId = display->getId();
+        if (displayId < 0) {
+            continue;
+        }
+
+        if (mDrawingState.colorMatrixChanged) {
+            display->setColorTransform(mDrawingState.colorMatrix);
+            status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix);
+            ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
+                    "display %d: %d", displayId, result);
+        }
+        for (auto& layer : display->getVisibleLayersSortedByZ()) {
+            if (layer->isHdrY410()) {
+                layer->forceClientComposition(displayId);
+            } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
+                        layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
+                    !display->hasHDR10Support()) {
+                layer->forceClientComposition(displayId);
+            } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
+                        layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
+                    !display->hasHLGSupport()) {
+                layer->forceClientComposition(displayId);
+            }
+
+            if (layer->getForceClientComposition(displayId)) {
+                ALOGV("[%s] Requesting Client composition", layer->getName().string());
+                layer->setCompositionType(displayId, HWC2::Composition::Client);
+                continue;
+            }
+
+            layer->setPerFrameData(display);
+        }
+
+        if (hasWideColorDisplay) {
+            ColorMode  colorMode;
+            Dataspace dataSpace;
+            RenderIntent renderIntent;
+            pickColorMode(display, &colorMode, &dataSpace, &renderIntent);
+            setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent);
+        }
+    }
+
+    mDrawingState.colorMatrixChanged = false;
+}
+
 void SurfaceFlinger::doDebugFlashRegions()
 {
     // is debugging enabled
@@ -1668,14 +1633,16 @@
     }
 }
 
-void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::preComposition()
 {
     ATRACE_CALL();
     ALOGV("preComposition");
 
+    mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
     bool needExtraInvalidate = false;
     mDrawingState.traverseInZOrder([&](Layer* layer) {
-        if (layer->onPreComposition(refreshStartTime)) {
+        if (layer->onPreComposition(mRefreshStartTime)) {
             needExtraInvalidate = true;
         }
     });
@@ -1744,7 +1711,7 @@
     getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
 }
 
-void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::postComposition()
 {
     ATRACE_CALL();
     ALOGV("postComposition");
@@ -1777,11 +1744,11 @@
     nsecs_t vsyncPhase = mPrimaryDispSync->computeNextRefresh(0);
     nsecs_t vsyncInterval = mPrimaryDispSync->getPeriod();
 
-    // We use the refreshStartTime which might be sampled a little later than
+    // We use the mRefreshStartTime which might be sampled a little later than
     // when we started doing work for this frame, but that should be okay
     // since updateCompositorTiming has snapping logic.
     updateCompositorTiming(
-        vsyncPhase, vsyncInterval, refreshStartTime, presentFenceTime);
+        vsyncPhase, vsyncInterval, mRefreshStartTime, presentFenceTime);
     CompositorTiming compositorTiming;
     {
         std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
@@ -2003,10 +1970,8 @@
     display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
 }
 
-void SurfaceFlinger::setUpHWComposer() {
-    ATRACE_CALL();
-    ALOGV("setUpHWComposer");
-
+void SurfaceFlinger::beginFrame()
+{
     for (const auto& [token, display] : mDisplays) {
         bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty();
         bool empty = display->getVisibleLayersSortedByZ().size() == 0;
@@ -2032,78 +1997,10 @@
             display->lastCompositionHadVisibleLayers = !empty;
         }
     }
+}
 
-    // build the h/w work list
-    if (CC_UNLIKELY(mGeometryInvalid)) {
-        mGeometryInvalid = false;
-        for (const auto& [token, display] : mDisplays) {
-            const auto displayId = display->getId();
-            if (displayId >= 0) {
-                const Vector<sp<Layer>>& currentLayers = display->getVisibleLayersSortedByZ();
-                for (size_t i = 0; i < currentLayers.size(); i++) {
-                    const auto& layer = currentLayers[i];
-                    if (!layer->hasHwcLayer(displayId)) {
-                        if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) {
-                            layer->forceClientComposition(displayId);
-                            continue;
-                        }
-                    }
-
-                    layer->setGeometry(display, i);
-                    if (mDebugDisableHWC || mDebugRegion) {
-                        layer->forceClientComposition(displayId);
-                    }
-                }
-            }
-        }
-    }
-
-    // Set the per-frame data
-    for (const auto& [token, display] : mDisplays) {
-        const auto displayId = display->getId();
-        if (displayId < 0) {
-            continue;
-        }
-
-        if (mDrawingState.colorMatrixChanged) {
-            display->setColorTransform(mDrawingState.colorMatrix);
-            status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix);
-            ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %d: %d",
-                     displayId, result);
-        }
-        for (auto& layer : display->getVisibleLayersSortedByZ()) {
-            if (layer->isHdrY410()) {
-                layer->forceClientComposition(displayId);
-            } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
-                        layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
-                    !display->hasHDR10Support()) {
-                layer->forceClientComposition(displayId);
-            } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
-                        layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
-                    !display->hasHLGSupport()) {
-                layer->forceClientComposition(displayId);
-            }
-
-            if (layer->getForceClientComposition(displayId)) {
-                ALOGV("[%s] Requesting Client composition", layer->getName().string());
-                layer->setCompositionType(displayId, HWC2::Composition::Client);
-                continue;
-            }
-
-            layer->setPerFrameData(display);
-        }
-
-        if (hasWideColorDisplay) {
-            ColorMode colorMode;
-            Dataspace dataSpace;
-            RenderIntent renderIntent;
-            pickColorMode(display, &colorMode, &dataSpace, &renderIntent);
-            setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent);
-        }
-    }
-
-    mDrawingState.colorMatrixChanged = false;
-
+void SurfaceFlinger::prepareFrame()
+{
     for (const auto& [token, display] : mDisplays) {
         if (!display->isPoweredOn()) {
             continue;
@@ -3377,9 +3274,8 @@
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
     const int uid = ipc->getCallingUid();
-
     if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
-            !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
+        !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
         return false;
     }
     return true;
@@ -4565,51 +4461,64 @@
 }
 
 status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
-    switch (code) {
-        case CREATE_CONNECTION:
-        case CREATE_DISPLAY:
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wswitch-enum"
+    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 GET_ANIMATION_FRAME_STATS:
-        case SET_POWER_MODE:
-        case GET_HDR_CAPABILITIES:
+        case CREATE_CONNECTION:
+        case CREATE_DISPLAY:
+        case DESTROY_DISPLAY:
         case ENABLE_VSYNC_INJECTIONS:
+        case GET_ACTIVE_COLOR_MODE:
+        case GET_ANIMATION_FRAME_STATS:
+        case GET_HDR_CAPABILITIES:
+        case SET_ACTIVE_CONFIG:
+        case SET_ACTIVE_COLOR_MODE:
         case INJECT_VSYNC:
-        {
-            // codes that require permission check
+        case SET_POWER_MODE: {
             if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
                 IPCThreadState* ipc = IPCThreadState::self();
                 ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
                         ipc->getCallingPid(), ipc->getCallingUid());
                 return PERMISSION_DENIED;
             }
-            break;
-        }
-        /*
-         * Calling setTransactionState is safe, because you need to have been
-         * granted a reference to Client* and Handle* to do anything with it.
-         *
-         * Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
-         */
-        case SET_TRANSACTION_STATE:
-        case CREATE_SCOPED_CONNECTION:
-        {
             return OK;
         }
-        case CAPTURE_SCREEN:
-        {
-            // codes that require permission check
+        case GET_LAYER_DEBUG_INFO: {
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
-            if ((uid != AID_GRAPHICS) &&
-                    !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
-                ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
+            if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
+                ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
                 return PERMISSION_DENIED;
             }
-            break;
+            return OK;
         }
-        case CAPTURE_LAYERS: {
+        // Used by apps to hook Choreographer to SurfaceFlinger.
+        case CREATE_DISPLAY_EVENT_CONNECTION:
+        // 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 GET_ACTIVE_CONFIG:
+        case GET_BUILT_IN_DISPLAY:
+        case GET_DISPLAY_COLOR_MODES:
+        case GET_DISPLAY_CONFIGS:
+        case GET_DISPLAY_STATS:
+        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.
+        case SET_TRANSACTION_STATE:
+        // Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
+        case CREATE_SCOPED_CONNECTION: {
+            return OK;
+        }
+        case CAPTURE_LAYERS:
+        case CAPTURE_SCREEN: {
+            // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
             const int uid = ipc->getCallingUid();
@@ -4618,15 +4527,37 @@
                 ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
                 return PERMISSION_DENIED;
             }
-            break;
+            return OK;
+        }
+        // The following codes are deprecated and should never be allowed to access SF.
+        case CONNECT_DISPLAY_UNUSED:
+        case CREATE_GRAPHIC_BUFFER_ALLOC_UNUSED: {
+            ALOGE("Attempting to access SurfaceFlinger with unused code: %u", code);
+            return PERMISSION_DENIED;
         }
     }
-    return OK;
+
+    // These codes are used for the IBinder protocol to either interrogate the recipient
+    // side of the transaction for its canonical interface descriptor or to dump its state.
+    // We let them pass by default.
+    if (code == IBinder::INTERFACE_TRANSACTION || code == IBinder::DUMP_TRANSACTION ||
+        code == IBinder::PING_TRANSACTION || code == IBinder::SHELL_COMMAND_TRANSACTION ||
+        code == IBinder::SYSPROPS_TRANSACTION) {
+        return OK;
+    }
+    // Numbers from 1000 to 1029 are currently use for backdoors. The code
+    // in onTransact verifies that the user is root, and has access to use SF.
+    if (code >= 1000 && code <= 1029) {
+        ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
+        return OK;
+    }
+    ALOGE("Permission Denial: SurfaceFlinger did not recognize request code: %u", code);
+    return PERMISSION_DENIED;
+#pragma clang diagnostic pop
 }
 
-status_t SurfaceFlinger::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
+status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                    uint32_t flags) {
     status_t credentialCheck = CheckTransactCodeCredentials(code);
     if (credentialCheck != OK) {
         return credentialCheck;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5ceea3a..f5d8eb4 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -648,8 +648,8 @@
     void computeVisibleRegions(const sp<const DisplayDevice>& display, Region& dirtyRegion,
                                Region& opaqueRegion);
 
-    void preComposition(nsecs_t refreshStartTime);
-    void postComposition(nsecs_t refreshStartTime);
+    void preComposition();
+    void postComposition();
     void updateCompositorTiming(
             nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
             std::shared_ptr<FenceTime>& presentFenceTime);
@@ -667,7 +667,18 @@
     void pickColorMode(const sp<DisplayDevice>& display, ui::ColorMode* outMode,
                        ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const;
 
-    void setUpHWComposer();
+    void calculateWorkingSet();
+    /*
+     * beginFrame - This function handles any pre-frame processing that needs to be
+     * prior to any CompositionInfo handling and is not dependent on data in
+     * CompositionInfo
+     */
+    void beginFrame();
+    /* 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 doTracing(const char* where);
@@ -863,6 +874,7 @@
     Mutex mHWVsyncLock;
     bool mPrimaryHWVsyncEnabled;
     bool mHWVsyncAvailable;
+    nsecs_t mRefreshStartTime;
 
     std::atomic<bool> mRefreshPending{false};
 
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index c511c5e..604aa7d 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -17,6 +17,7 @@
     defaults: ["surfaceflinger_defaults"],
     test_suites: ["device-tests"],
     srcs: [
+        "Credentials_test.cpp",
         "Stress_test.cpp",
         "SurfaceInterceptor_test.cpp",
         "Transaction_test.cpp",
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
new file mode 100644
index 0000000..cd57411
--- /dev/null
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -0,0 +1,322 @@
+#include <algorithm>
+#include <functional>
+#include <limits>
+#include <ostream>
+
+#include <gtest/gtest.h>
+
+#include <gui/ISurfaceComposer.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <private/android_filesystem_config.h>
+#include <private/gui/ComposerService.h>
+
+#include <ui/DisplayInfo.h>
+#include <utils/String8.h>
+
+namespace android {
+
+using Transaction = SurfaceComposerClient::Transaction;
+
+namespace {
+const String8 DISPLAY_NAME("Credentials Display Test");
+const String8 SURFACE_NAME("Test Surface Name");
+const int32_t MIN_LAYER_Z = 0;
+const int32_t MAX_LAYER_Z = std::numeric_limits<int32_t>::max();
+const uint32_t ROTATION = 0;
+const float FRAME_SCALE = 1.0f;
+} // namespace
+
+/**
+ * This class tests the CheckCredentials method in SurfaceFlinger.
+ * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
+ * return anything meaningful.
+ */
+class CredentialsTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        // Start the tests as root.
+        seteuid(AID_ROOT);
+
+        ASSERT_NO_FATAL_FAILURE(initClient());
+    }
+
+    void TearDown() override {
+        mComposerClient->dispose();
+        mBGSurfaceControl.clear();
+        mComposerClient.clear();
+        // Finish the tests as root.
+        seteuid(AID_ROOT);
+    }
+
+    sp<IBinder> mDisplay;
+    sp<IBinder> mVirtualDisplay;
+    sp<SurfaceComposerClient> mComposerClient;
+    sp<SurfaceControl> mBGSurfaceControl;
+    sp<SurfaceControl> mVirtualSurfaceControl;
+
+    void initClient() {
+        mComposerClient = new SurfaceComposerClient;
+        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
+    }
+
+    void setupBackgroundSurface() {
+        mDisplay = SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
+        DisplayInfo info;
+        SurfaceComposerClient::getDisplayInfo(mDisplay, &info);
+        const ssize_t displayWidth = info.w;
+        const ssize_t displayHeight = info.h;
+
+        // Background surface
+        mBGSurfaceControl =
+                mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
+                                               PIXEL_FORMAT_RGBA_8888, 0);
+        ASSERT_TRUE(mBGSurfaceControl != nullptr);
+        ASSERT_TRUE(mBGSurfaceControl->isValid());
+
+        Transaction t;
+        t.setDisplayLayerStack(mDisplay, 0);
+        ASSERT_EQ(NO_ERROR,
+                  t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
+    }
+
+    void setupVirtualDisplay() {
+        mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
+        const ssize_t displayWidth = 100;
+        const ssize_t displayHeight = 100;
+
+        // Background surface
+        mVirtualSurfaceControl =
+                mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
+                                               PIXEL_FORMAT_RGBA_8888, 0);
+        ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
+        ASSERT_TRUE(mVirtualSurfaceControl->isValid());
+
+        Transaction t;
+        t.setDisplayLayerStack(mVirtualDisplay, 0);
+        ASSERT_EQ(NO_ERROR,
+                  t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
+                          .show(mVirtualSurfaceControl)
+                          .apply());
+    }
+
+    /**
+     * Sets UID to imitate Graphic's process.
+     */
+    void setGraphicsUID() {
+        seteuid(AID_ROOT);
+        seteuid(AID_GRAPHICS);
+    }
+
+    /**
+     * Sets UID to imitate System's process.
+     */
+    void setSystemUID() {
+        seteuid(AID_ROOT);
+        seteuid(AID_SYSTEM);
+    }
+
+    /**
+     * Sets UID to imitate a process that doesn't have any special privileges in
+     * our code.
+     */
+    void setBinUID() {
+        seteuid(AID_ROOT);
+        seteuid(AID_BIN);
+    }
+
+    /**
+     * Template function the check a condition for different types of users: root
+     * graphics, system, and non-supported user. Root, graphics, and system should
+     * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
+     */
+    template <typename T>
+    void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
+        // Check with root.
+        seteuid(AID_ROOT);
+        ASSERT_EQ(privilegedValue, condition());
+
+        // Check as a Graphics user.
+        setGraphicsUID();
+        ASSERT_EQ(privilegedValue, condition());
+
+        // Check as a system user.
+        setSystemUID();
+        ASSERT_EQ(privilegedValue, condition());
+
+        // Check as a non-supported user.
+        setBinUID();
+        ASSERT_EQ(unprivilegedValue, condition());
+    }
+};
+
+TEST_F(CredentialsTest, ClientInitTest) {
+    // Root can init can init the client.
+    ASSERT_NO_FATAL_FAILURE(initClient());
+
+    // Graphics can init the client.
+    setGraphicsUID();
+    ASSERT_NO_FATAL_FAILURE(initClient());
+
+    // System can init the client.
+    setSystemUID();
+    ASSERT_NO_FATAL_FAILURE(initClient());
+
+    // No one else can init the client.
+    setBinUID();
+    mComposerClient = new SurfaceComposerClient;
+    ASSERT_EQ(NO_INIT, mComposerClient->initCheck());
+}
+
+TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
+    std::function<bool()> condition = [=]() {
+        sp<IBinder> display(
+                SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+        return (display != nullptr);
+    };
+    // Anyone can access display information.
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
+}
+
+TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
+    // The following methods are tested with a UID that is not root, graphics,
+    // or system, to show that anyone can access them.
+    setBinUID();
+    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    ASSERT_TRUE(display != nullptr);
+
+    DisplayInfo info;
+    ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
+
+    Vector<DisplayInfo> configs;
+    ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+
+    ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
+
+    ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
+              SurfaceComposerClient::getActiveColorMode(display));
+}
+
+TEST_F(CredentialsTest, GetDisplayColorModesTest) {
+    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    std::function<status_t()> condition = [=]() {
+        Vector<ui::ColorMode> outColorModes;
+        return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
+    };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
+}
+
+TEST_F(CredentialsTest, SetActiveConfigTest) {
+    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    std::function<status_t()> condition = [=]() {
+        return SurfaceComposerClient::setActiveConfig(display, 0);
+    };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
+}
+
+TEST_F(CredentialsTest, SetActiveColorModeTest) {
+    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    std::function<status_t()> condition = [=]() {
+        return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
+    };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
+}
+
+TEST_F(CredentialsTest, CreateSurfaceTest) {
+    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    DisplayInfo info;
+    SurfaceComposerClient::getDisplayInfo(display, &info);
+    const ssize_t displayWidth = info.w;
+    const ssize_t displayHeight = info.h;
+
+    std::function<bool()> condition = [=]() {
+        mBGSurfaceControl =
+                mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
+                                               PIXEL_FORMAT_RGBA_8888, 0);
+        return mBGSurfaceControl != nullptr && mBGSurfaceControl->isValid();
+    };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+}
+
+TEST_F(CredentialsTest, CreateDisplayTest) {
+    std::function<bool()> condition = [=]() {
+        sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
+        return testDisplay.get() != nullptr;
+    };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+
+    condition = [=]() {
+        sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
+        return testDisplay.get() != nullptr;
+    };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+}
+
+TEST_F(CredentialsTest, DISABLED_DestroyDisplayTest) {
+    setupVirtualDisplay();
+
+    DisplayInfo info;
+    ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
+    SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
+    // This test currently fails. TODO(b/112002626): Find a way to properly create
+    // a display in the test environment, so that destroy display can remove it.
+    ASSERT_EQ(NAME_NOT_FOUND, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
+}
+
+TEST_F(CredentialsTest, CaptureTest) {
+    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    std::function<status_t()> condition = [=]() {
+        sp<GraphicBuffer> outBuffer;
+        return ScreenshotClient::capture(display, Rect(), 0 /*reqWidth*/, 0 /*reqHeight*/,
+                                         MIN_LAYER_Z, MAX_LAYER_Z, false, ROTATION, &outBuffer);
+    };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
+}
+
+TEST_F(CredentialsTest, CaptureLayersTest) {
+    setupBackgroundSurface();
+    sp<GraphicBuffer> outBuffer;
+    std::function<status_t()> condition = [=]() {
+        sp<GraphicBuffer> outBuffer;
+        return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(), Rect(), FRAME_SCALE,
+                                               &outBuffer);
+    };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
+}
+
+/**
+ * Test for methods accessible directly through SurfaceFlinger:
+ */
+TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
+    setupBackgroundSurface();
+    sp<IGraphicBufferProducer> producer =
+            mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+    std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
+    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
+}
+
+TEST_F(CredentialsTest, GetLayerDebugInfo) {
+    setupBackgroundSurface();
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+    // Historically, only root and shell can access the getLayerDebugInfo which
+    // is called when we call dumpsys. I don't see a reason why we should change this.
+    std::vector<LayerDebugInfo> outLayers;
+    // Check with root.
+    seteuid(AID_ROOT);
+    ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+
+    // Check as a shell.
+    seteuid(AID_SHELL);
+    ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+
+    // Check as anyone else.
+    seteuid(AID_ROOT);
+    seteuid(AID_BIN);
+    ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
+}
+} // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 731e628..1319e12 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize"
+            "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize"
         }
 }