Merge "SurfaceFlinger: get present time from SF and not from Scheduler" into qt-r1-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 7ac0eb7..a4b00f8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -890,6 +890,7 @@
     setTagsProperty(0);
     clearAppProperties();
     pokeBinderServices();
+    pokeHalServices();
 
     if (g_tracePdx) {
         ServiceUtility::PokeServices();
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 5427ff8..afa3d33 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2086,8 +2086,8 @@
 
 const char* Parcel::readCString() const
 {
-    const size_t avail = mDataSize-mDataPos;
-    if (avail > 0) {
+    if (mDataPos < mDataSize) {
+        const size_t avail = mDataSize-mDataPos;
         const char* str = reinterpret_cast<const char*>(mData+mDataPos);
         // is the string's trailing NUL within the parcel's valid bounds?
         const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
@@ -2835,10 +2835,16 @@
                 }
                 release_object(proc, *flat, this, &mOpenAshmemSize);
             }
-            binder_size_t* objects =
-                (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
-            if (objects) {
-                mObjects = objects;
+
+            if (objectsSize == 0) {
+                free(mObjects);
+                mObjects = nullptr;
+            } else {
+                binder_size_t* objects =
+                    (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
+                if (objects) {
+                    mObjects = objects;
+                }
             }
             mObjectsSize = objectsSize;
             mNextObjectHint = 0;
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 8b33a56..0ad99ce 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -102,13 +102,23 @@
     // Skip over fat response headers.  Not used (or propagated) in native code.
     if (mException == EX_HAS_REPLY_HEADER) {
         // Note that the header size includes the 4 byte size field.
-        const int32_t header_start = parcel.dataPosition();
+        const size_t header_start = parcel.dataPosition();
+        // Get available size before reading more
+        const size_t header_avail = parcel.dataAvail();
+
         int32_t header_size;
         status = parcel.readInt32(&header_size);
         if (status != OK) {
             setFromStatusT(status);
             return status;
         }
+
+        if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+            android_errorWriteLog(0x534e4554, "132650049");
+            setFromStatusT(UNKNOWN_ERROR);
+            return UNKNOWN_ERROR;
+        }
+
         parcel.setDataPosition(header_start + header_size);
         // And fat response headers are currently only used when there are no
         // exceptions, so act like there was no error.
@@ -135,19 +145,36 @@
         setFromStatusT(status);
         return status;
     }
+    if (remote_stack_trace_header_size < 0 ||
+        static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) {
+
+        android_errorWriteLog(0x534e4554, "132650049");
+        setFromStatusT(UNKNOWN_ERROR);
+        return UNKNOWN_ERROR;
+    }
     parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
 
     if (mException == EX_SERVICE_SPECIFIC) {
         status = parcel.readInt32(&mErrorCode);
     } else if (mException == EX_PARCELABLE) {
         // Skip over the blob of Parcelable data
-        const int32_t header_start = parcel.dataPosition();
+        const size_t header_start = parcel.dataPosition();
+        // Get available size before reading more
+        const size_t header_avail = parcel.dataAvail();
+
         int32_t header_size;
         status = parcel.readInt32(&header_size);
         if (status != OK) {
             setFromStatusT(status);
             return status;
         }
+
+        if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+            android_errorWriteLog(0x534e4554, "132650049");
+            setFromStatusT(UNKNOWN_ERROR);
+            return UNKNOWN_ERROR;
+        }
+
         parcel.setDataPosition(header_start + header_size);
     }
     if (status != OK) {
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 407f77d..1c5fa52 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -534,60 +534,73 @@
     mDebugLayersGLES = layers;
 }
 
+// Return true if all the required libraries from vndk and sphal namespace are
+// linked to the Game Driver namespace correctly.
+bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
+    const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
+    if (llndkLibraries.empty()) {
+        return false;
+    }
+    if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
+        ALOGE("Failed to link default namespace[%s]", dlerror());
+        return false;
+    }
+
+    const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
+    if (vndkspLibraries.empty()) {
+        return false;
+    }
+    if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+        ALOGE("Failed to link vndk namespace[%s]", dlerror());
+        return false;
+    }
+
+    if (mSphalLibraries.empty()) {
+        return true;
+    }
+
+    // Make additional libraries in sphal to be accessible
+    auto sphalNamespace = android_get_exported_namespace("sphal");
+    if (!sphalNamespace) {
+        ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
+              mSphalLibraries.c_str());
+        return false;
+    }
+
+    if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
+        ALOGE("Failed to link sphal namespace[%s]", dlerror());
+        return false;
+    }
+
+    return true;
+}
+
 android_namespace_t* GraphicsEnv::getDriverNamespace() {
-    static std::once_flag once;
-    std::call_once(once, [this]() {
-        if (mDriverPath.empty()) return;
+    std::lock_guard<std::mutex> lock(mNamespaceMutex);
 
-        auto vndkNamespace = android_get_exported_namespace("vndk");
-        if (!vndkNamespace) return;
+    if (mDriverNamespace) {
+        return mDriverNamespace;
+    }
 
-        mDriverNamespace = android_create_namespace("gfx driver",
-                                                    mDriverPath.c_str(), // ld_library_path
-                                                    mDriverPath.c_str(), // default_library_path
-                                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
-                                                    nullptr, // permitted_when_isolated_path
-                                                    nullptr);
+    if (mDriverPath.empty()) {
+        return nullptr;
+    }
 
-        const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
-        if (llndkLibraries.empty()) {
-            mDriverNamespace = nullptr;
-            return;
-        }
-        if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
-            ALOGE("Failed to link default namespace[%s]", dlerror());
-            mDriverNamespace = nullptr;
-            return;
-        }
+    auto vndkNamespace = android_get_exported_namespace("vndk");
+    if (!vndkNamespace) {
+        return nullptr;
+    }
 
-        const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
-        if (vndkspLibraries.empty()) {
-            mDriverNamespace = nullptr;
-            return;
-        }
-        if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
-            ALOGE("Failed to link vndk namespace[%s]", dlerror());
-            mDriverNamespace = nullptr;
-            return;
-        }
+    mDriverNamespace = android_create_namespace("gfx driver",
+                                                mDriverPath.c_str(), // ld_library_path
+                                                mDriverPath.c_str(), // default_library_path
+                                                ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                                nullptr, // permitted_when_isolated_path
+                                                nullptr);
 
-        if (mSphalLibraries.empty()) return;
-
-        // Make additional libraries in sphal to be accessible
-        auto sphalNamespace = android_get_exported_namespace("sphal");
-        if (!sphalNamespace) {
-            ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
-                  mSphalLibraries.c_str());
-            mDriverNamespace = nullptr;
-            return;
-        }
-
-        if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
-            ALOGE("Failed to link sphal namespace[%s]", dlerror());
-            mDriverNamespace = nullptr;
-            return;
-        }
-    });
+    if (!linkDriverNamespaceLocked(vndkNamespace)) {
+        mDriverNamespace = nullptr;
+    }
 
     return mDriverNamespace;
 }
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 7d62750..f5d19db 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -129,6 +129,7 @@
     void* loadLibrary(std::string name);
     bool checkAngleRules(void* so);
     void updateUseAngle();
+    bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace);
 
     GraphicsEnv() = default;
     std::string mDriverPath;
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index f5cf1c4..b8faa2d 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -32,10 +32,11 @@
 
 // ---------------------------------------------------------------------------
 
-DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
+DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource,
+                                           ISurfaceComposer::ConfigChanged configChanged) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     if (sf != nullptr) {
-        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
+        mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged);
         if (mEventConnection != nullptr) {
             mDataChannel = std::make_unique<gui::BitTube>();
             mEventConnection->stealReceiveChannel(mDataChannel.get());
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 6c9d81a..e487792 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -278,8 +278,8 @@
         return NO_ERROR;
     }
 
-    virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource)
-    {
+    virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource,
+                                                                     ConfigChanged configChanged) {
         Parcel data, reply;
         sp<IDisplayEventConnection> result;
         int err = data.writeInterfaceToken(
@@ -288,6 +288,7 @@
             return result;
         }
         data.writeInt32(static_cast<int32_t>(vsyncSource));
+        data.writeInt32(static_cast<int32_t>(configChanged));
         err = remote()->transact(
                 BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
                 data, &reply);
@@ -1155,8 +1156,11 @@
         }
         case CREATE_DISPLAY_EVENT_CONNECTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IDisplayEventConnection> connection(createDisplayEventConnection(
-                    static_cast<ISurfaceComposer::VsyncSource>(data.readInt32())));
+            auto vsyncSource = static_cast<ISurfaceComposer::VsyncSource>(data.readInt32());
+            auto configChanged = static_cast<ISurfaceComposer::ConfigChanged>(data.readInt32());
+
+            sp<IDisplayEventConnection> connection(
+                    createDisplayEventConnection(vsyncSource, configChanged));
             reply->writeStrongBinder(IInterface::asBinder(connection));
             return NO_ERROR;
         }
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 22de751..a558cf9 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -88,10 +88,13 @@
      * DisplayEventReceiver creates and registers an event connection with
      * SurfaceFlinger. VSync events are disabled by default. Call setVSyncRate
      * or requestNextVsync to receive them.
+     * To receive Config Changed events specify this in the constructor.
      * Other events start being delivered immediately.
      */
     explicit DisplayEventReceiver(
-            ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
+            ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
+            ISurfaceComposer::ConfigChanged configChanged =
+                    ISurfaceComposer::eConfigChangedSuppress);
 
     /*
      * ~DisplayEventReceiver severs the connection with SurfaceFlinger, new events
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e2f7736..c84910b 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -90,6 +90,8 @@
         eVsyncSourceSurfaceFlinger = 1
     };
 
+    enum ConfigChanged { eConfigChangedSuppress = 0, eConfigChangedDispatch = 1 };
+
     /*
      * Create a connection with SurfaceFlinger.
      */
@@ -97,7 +99,8 @@
 
     /* return an IDisplayEventConnection */
     virtual sp<IDisplayEventConnection> createDisplayEventConnection(
-            VsyncSource vsyncSource = eVsyncSourceApp) = 0;
+            VsyncSource vsyncSource = eVsyncSourceApp,
+            ConfigChanged configChanged = eConfigChangedSuppress) = 0;
 
     /* create a virtual display
      * requires ACCESS_SURFACE_FLINGER permission.
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 960cf18..d370858 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -548,8 +548,8 @@
     }
 
     sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
-    sp<IDisplayEventConnection> createDisplayEventConnection(ISurfaceComposer::VsyncSource)
-            override {
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            ISurfaceComposer::VsyncSource, ISurfaceComposer::ConfigChanged) override {
         return nullptr;
     }
     sp<IBinder> createDisplay(const String8& /*displayName*/,
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index c0bace8..abc7a72 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -208,6 +208,10 @@
     defaults: ["gles_libs_defaults"],
     srcs: ["GLES2/gl2.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv2\""],
+
+    // Bug: http://b/133874658  Disable native_coverage as we investigate a
+    // crash in surfaceflinger on coverage-enabled cuttlefish builds.
+    native_coverage: false,
 }
 
 //##############################################################################
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index d5c46c6..038a432 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -84,6 +84,11 @@
     return android_load_sphal_library(path, mode);
 }
 
+static int do_android_unload_sphal_library(void* dso) {
+    ATRACE_CALL();
+    return android_unload_sphal_library(dso);
+}
+
 Loader::driver_t::driver_t(void* gles)
 {
     dso[0] = gles;
@@ -180,11 +185,81 @@
     "ro.board.platform",
 };
 
+static bool should_unload_system_driver(egl_connection_t* cnx) {
+    // Return false if the system driver has been unloaded once.
+    if (cnx->systemDriverUnloaded) {
+        return false;
+    }
+
+    // Return true if Angle namespace is set.
+    android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
+    if (ns) {
+        return true;
+    }
+
+#ifndef __ANDROID_VNDK__
+    // Return true if updated driver namespace is set.
+    ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+    if (ns) {
+        return true;
+    }
+#endif
+
+    return false;
+}
+
+static void uninit_api(char const* const* api, __eglMustCastToProperFunctionPointerType* curr) {
+    while (*api) {
+        *curr++ = nullptr;
+        api++;
+    }
+}
+
+void Loader::unload_system_driver(egl_connection_t* cnx) {
+    ATRACE_CALL();
+
+    uninit_api(gl_names,
+               (__eglMustCastToProperFunctionPointerType*)&cnx
+                       ->hooks[egl_connection_t::GLESv2_INDEX]
+                       ->gl);
+    uninit_api(gl_names,
+               (__eglMustCastToProperFunctionPointerType*)&cnx
+                       ->hooks[egl_connection_t::GLESv1_INDEX]
+                       ->gl);
+    uninit_api(egl_names, (__eglMustCastToProperFunctionPointerType*)&cnx->egl);
+
+    if (cnx->dso) {
+        ALOGD("Unload system gl driver.");
+        driver_t* hnd = (driver_t*)cnx->dso;
+        if (hnd->dso[2]) {
+            do_android_unload_sphal_library(hnd->dso[2]);
+        }
+        if (hnd->dso[1]) {
+            do_android_unload_sphal_library(hnd->dso[1]);
+        }
+        if (hnd->dso[0]) {
+            do_android_unload_sphal_library(hnd->dso[0]);
+        }
+        cnx->dso = nullptr;
+    }
+
+    cnx->systemDriverUnloaded = true;
+}
+
 void* Loader::open(egl_connection_t* cnx)
 {
     ATRACE_CALL();
     const nsecs_t openTime = systemTime();
 
+    if (should_unload_system_driver(cnx)) {
+        unload_system_driver(cnx);
+    }
+
+    // If a driver has been loaded, return the driver directly.
+    if (cnx->dso) {
+        return cnx->dso;
+    }
+
     setEmulatorGlesValue();
 
     // Check if we should use ANGLE early, so loading each driver doesn't require repeated queries.
@@ -244,9 +319,15 @@
                         "couldn't find an OpenGL ES implementation, make sure you set %s or %s",
                         HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]);
 
-    cnx->libEgl   = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
-    cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
-    cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+    if (!cnx->libEgl) {
+        cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
+    }
+    if (!cnx->libGles1) {
+        cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+    }
+    if (!cnx->libGles2) {
+        cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
+    }
 
     if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
         android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
@@ -584,6 +665,7 @@
         return nullptr;
     }
 
+    ALOGD("Load updated gl driver.");
     android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL_UPDATED);
     driver_t* hnd = nullptr;
     void* dso = load_updated_driver("GLES", ns);
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 0292d02..6f31ab4 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -58,6 +58,7 @@
     driver_t* attempt_to_load_angle(egl_connection_t* cnx);
     driver_t* attempt_to_load_updated_driver(egl_connection_t* cnx);
     driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
+    void unload_system_driver(egl_connection_t* cnx);
     void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
 
     static __attribute__((noinline))
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 8870d5f..25b1009 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -187,13 +187,9 @@
 
     // dynamically load our EGL implementation
     egl_connection_t* cnx = &gEGLImpl;
-    if (cnx->dso == nullptr) {
-        cnx->hooks[egl_connection_t::GLESv1_INDEX] =
-                &gHooks[egl_connection_t::GLESv1_INDEX];
-        cnx->hooks[egl_connection_t::GLESv2_INDEX] =
-                &gHooks[egl_connection_t::GLESv2_INDEX];
-        cnx->dso = loader.open(cnx);
-    }
+    cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX];
+    cnx->hooks[egl_connection_t::GLESv2_INDEX] = &gHooks[egl_connection_t::GLESv2_INDEX];
+    cnx->dso = loader.open(cnx);
 
     // Check to see if any layers are enabled and route functions through them
     if (cnx->dso) {
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 8841a3b..67d69b4 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -217,7 +217,7 @@
     Loader& loader(Loader::getInstance());
 
     egl_connection_t* const cnx = &gEGLImpl;
-    if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
+    if (cnx->dso) {
         EGLDisplay dpy = EGL_NO_DISPLAY;
 
         if (cnx->useAngle) {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 9e112cc..7bb9b59 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -44,7 +44,11 @@
         GLESv2_INDEX = 1
     };
 
-    inline egl_connection_t() : dso(nullptr) {
+    inline egl_connection_t() : dso(nullptr),
+                                libEgl(nullptr),
+                                libGles1(nullptr),
+                                libGles2(nullptr),
+                                systemDriverUnloaded(false) {
 
         char const* const* entries = platform_names;
         EGLFuncPointer* curr = reinterpret_cast<EGLFuncPointer*>(&platform);
@@ -76,6 +80,7 @@
     void*               libGles1;
     void*               libGles2;
 
+    bool                systemDriverUnloaded;
     bool                shouldUseAngle; // Should we attempt to load ANGLE
     bool                angleDecided;   // Have we tried to load ANGLE
     bool                useAngle;       // Was ANGLE successfully loaded
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index ef1a224..6a7f279 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -82,7 +82,7 @@
 // Check if the "deep touch" feature is on.
 static bool deepPressEnabled() {
     std::string flag_value = server_configurable_flags::GetServerConfigurableFlag(
-            INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "true");
+            INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "false");
     std::transform(flag_value.begin(), flag_value.end(), flag_value.begin(), ::tolower);
     if (flag_value == "1" || flag_value == "true") {
         ALOGI("Deep press feature enabled.");
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 31a2dab..c2ff4c9 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -2172,9 +2172,8 @@
         return;
     }
 
-    int32_t displayId = inputWindowHandle->getInfo()->displayId;
     sp<InputWindowHandle> focusedWindowHandle =
-            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+            getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
 
     bool hasFocusChanged = !focusedWindowHandle || focusedWindowHandle->getToken() != newToken;
 
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index fcd4f29..717f317 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -45,7 +45,9 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
 
-static status_t StatusFromResult(Result result) {
+namespace {
+
+status_t statusFromResult(Result result) {
     switch (result) {
         case Result::OK:
             return OK;
@@ -71,6 +73,8 @@
     INTERNAL_WAKE =  1 << 16,
 };
 
+}  // anonymous namespace
+
 void SensorsHalDeathReceivier::serviceDied(
         uint64_t /* cookie */,
         const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
@@ -105,7 +109,7 @@
     initializeSensorList();
 
     mIsDirectReportSupported =
-           (checkReturn(mSensors->unregisterDirectChannel(-1)) != Result::INVALID_OPERATION);
+            (checkReturnAndGetStatus(mSensors->unregisterDirectChannel(-1)) != INVALID_OPERATION);
 }
 
 void SensorDevice::initializeSensorList() {
@@ -122,7 +126,7 @@
                     convertToSensor(list[i], &sensor);
                     // Sanity check and clamp power if it is 0 (or close)
                     if (sensor.power < minPowerMa) {
-                        ALOGE("Reported power %f not deemed sane, clamping to %f",
+                        ALOGI("Reported power %f not deemed sane, clamping to %f",
                               sensor.power, minPowerMa);
                         sensor.power = minPowerMa;
                     }
@@ -217,10 +221,10 @@
                 mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
                 mWakeLockQueueFlag != nullptr);
 
-        status_t status = StatusFromResult(checkReturn(mSensors->initialize(
+        status_t status = checkReturnAndGetStatus(mSensors->initialize(
                 *mEventQueue->getDesc(),
                 *mWakeLockQueue->getDesc(),
-                new SensorsCallback())));
+                new SensorsCallback()));
 
         if (status != NO_ERROR) {
             connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
@@ -270,6 +274,8 @@
     bool didChange = false;
 
     if (oldSensorList.size() != newSensorList.size()) {
+        ALOGI("Sensor list size changed from %zu to %zu", oldSensorList.size(),
+              newSensorList.size());
         didChange = true;
     }
 
@@ -281,6 +287,7 @@
             if (prevSensor.handle == newSensor.handle) {
                 found = true;
                 if (!sensorIsEquivalent(prevSensor, newSensor)) {
+                    ALOGI("Sensor %s not equivalent to previous version", newSensor.name);
                     didChange = true;
                 }
             }
@@ -289,6 +296,7 @@
         if (!found) {
             // Could not find the new sensor in the old list of sensors, the lists must
             // have changed.
+            ALOGI("Sensor %s (handle %d) did not exist before", newSensor.name, newSensor.handle);
             didChange = true;
         }
     }
@@ -423,7 +431,7 @@
                         convertToSensorEvents(events, dynamicSensorsAdded, buffer);
                         err = (ssize_t)events.size();
                     } else {
-                        err = StatusFromResult(result);
+                        err = statusFromResult(result);
                     }
                 });
 
@@ -621,7 +629,7 @@
     if (actuateHardware) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
                  enabled);
-        err = StatusFromResult(checkReturn(mSensors->activate(handle, enabled)));
+        err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
         ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
                  strerror(-err));
 
@@ -694,9 +702,8 @@
     if (prevBestBatchParams != info.bestBatchParams) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
                  info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
-        err = StatusFromResult(
-                checkReturn(mSensors->batch(
-                    handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch)));
+        err = checkReturnAndGetStatus(mSensors->batch(
+                handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch));
         if (err != NO_ERROR) {
             ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s",
                   mSensors.get(), handle, info.bestBatchParams.mTSample,
@@ -720,7 +727,7 @@
     if (mSensors == nullptr) return NO_INIT;
     if (isClientDisabled(ident)) return INVALID_OPERATION;
     ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
-    return StatusFromResult(checkReturn(mSensors->flush(handle)));
+    return checkReturnAndGetStatus(mSensors->flush(handle));
 }
 
 bool SensorDevice::isClientDisabled(void* ident) {
@@ -753,16 +760,14 @@
         const int sensor_handle = mActivationCount.keyAt(i);
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
                    sensor_handle);
-        status_t err = StatusFromResult(
-                checkReturn(mSensors->batch(
-                    sensor_handle,
-                    info.bestBatchParams.mTSample,
-                    info.bestBatchParams.mTBatch)));
+        status_t err = checkReturnAndGetStatus(mSensors->batch(
+                sensor_handle,
+                info.bestBatchParams.mTSample,
+                info.bestBatchParams.mTBatch));
         ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
 
         if (err == NO_ERROR) {
-            err = StatusFromResult(
-                    checkReturn(mSensors->activate(sensor_handle, 1 /* enabled */)));
+            err = checkReturnAndGetStatus(mSensors->activate(sensor_handle, 1 /* enabled */));
             ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
         }
 
@@ -810,14 +815,13 @@
     Event ev;
     convertFromSensorEvent(*injected_sensor_event, &ev);
 
-    return StatusFromResult(checkReturn(mSensors->injectSensorData(ev)));
+    return checkReturnAndGetStatus(mSensors->injectSensorData(ev));
 }
 
 status_t SensorDevice::setMode(uint32_t mode) {
     if (mSensors == nullptr) return NO_INIT;
-    return StatusFromResult(
-            checkReturn(mSensors->setOperationMode(
-                    static_cast<hardware::sensors::V1_0::OperationMode>(mode))));
+    return checkReturnAndGetStatus(mSensors->setOperationMode(
+            static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
 }
 
 int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
@@ -855,7 +859,7 @@
                 if (result == Result::OK) {
                     ret = channelHandle;
                 } else {
-                    ret = StatusFromResult(result);
+                    ret = statusFromResult(result);
                 }
             }));
     return ret;
@@ -894,12 +898,12 @@
     checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
             [&ret, rate] (auto result, auto token) {
                 if (rate == RateLevel::STOP) {
-                    ret = StatusFromResult(result);
+                    ret = statusFromResult(result);
                 } else {
                     if (result == Result::OK) {
                         ret = token;
                     } else {
-                        ret = StatusFromResult(result);
+                        ret = statusFromResult(result);
                     }
                 }
             }));
@@ -1008,7 +1012,7 @@
 }
 
 void SensorDevice::handleHidlDeath(const std::string & detail) {
-    if (!SensorDevice::getInstance().mSensors->supportsMessageQueues()) {
+    if (!mSensors->supportsMessageQueues()) {
         // restart is the only option at present.
         LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
     } else {
@@ -1016,5 +1020,10 @@
     }
 }
 
+status_t SensorDevice::checkReturnAndGetStatus(const Return<Result>& ret) {
+    checkReturn(ret);
+    return (!ret.isOk()) ? DEAD_OBJECT : statusFromResult(ret);
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index e8685c2..d2c6994 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -211,14 +211,14 @@
     status_t batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
                          int64_t maxBatchReportLatencyNs);
 
-    static void handleHidlDeath(const std::string &detail);
+    void handleHidlDeath(const std::string &detail);
     template<typename T>
-    static Return<T> checkReturn(Return<T> &&ret) {
+    void checkReturn(const Return<T>& ret) {
         if (!ret.isOk()) {
             handleHidlDeath(ret.description());
         }
-        return std::move(ret);
     }
+    status_t checkReturnAndGetStatus(const Return<Result>& ret);
     //TODO(b/67425500): remove waiter after bug is resolved.
     sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
 
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index a2b6ab6..9d72399 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -545,6 +545,12 @@
         if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled &&
             presentTimeIsCurrent) {
             point->setFrameAvailable();
+            sp<Layer> requestedSyncLayer = point->getRequestedSyncLayer();
+            if (requestedSyncLayer) {
+                // Need to update the transaction flag to ensure the layer's pending transaction
+                // gets applied.
+                requestedSyncLayer->setTransactionFlags(eTransactionNeeded);
+            }
         }
     }
 }
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 203bd72..2abc1a7 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -50,12 +50,6 @@
     mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
     mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
 }
-BufferStateLayer::~BufferStateLayer() {
-    if (mActiveBuffer != nullptr) {
-        auto& engine(mFlinger->getRenderEngine());
-        engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
-    }
-}
 
 // -----------------------------------------------------------------------
 // Interface implementation for Layer
@@ -571,11 +565,6 @@
         return BAD_VALUE;
     }
 
-    if (mActiveBuffer != nullptr) {
-        // todo: get this to work with BufferStateLayerCache
-        auto& engine(mFlinger->getRenderEngine());
-        engine.unbindExternalTextureBuffer(mActiveBuffer->getId());
-    }
     mActiveBuffer = s.buffer;
     mActiveBufferFence = s.acquireFence;
     auto& layerCompositionState = getCompositionLayer()->editState().frontEnd;
@@ -621,6 +610,10 @@
     }
 }
 
+void BufferStateLayer::bufferErased(const client_cache_t& clientCacheId) {
+    mFlinger->getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id);
+}
+
 void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
     std::lock_guard lock(mMutex);
     if (!clientCacheId.isValid()) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 4e2bc45..db8ae0d 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -34,7 +34,6 @@
 class BufferStateLayer : public BufferLayer {
 public:
     explicit BufferStateLayer(const LayerCreationArgs&);
-    ~BufferStateLayer() override;
 
     // -----------------------------------------------------------------------
     // Interface implementation for Layer
@@ -103,6 +102,9 @@
     bool fenceHasSignaled() const override;
     bool framePresentTimeIsCurrent() const override;
 
+    // Inherit from ClientCache::ErasedRecipient
+    void bufferErased(const client_cache_t& clientCacheId) override;
+
 private:
     nsecs_t getDesiredPresentTime() override;
     std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index cc5a5b5..7f47a2e 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -24,6 +24,7 @@
 
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
 #include <gui/BufferQueue.h>
+#include <hidl/HidlTransportSupport.h>
 #include <hidl/HidlTransportUtils.h>
 
 namespace android {
@@ -229,6 +230,7 @@
 
 void Composer::registerCallback(const sp<IComposerCallback>& callback)
 {
+    android::hardware::setMinSchedulerPolicy(callback, SCHED_FIFO, 2);
     auto ret = mClient->registerCallback(callback);
     if (!ret.isOk()) {
         ALOGE("failed to register IComposerCallback");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 379b004..898f3bc 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -144,28 +144,47 @@
  */
 void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
 
-void Layer::onRemovedFromCurrentState() {
-    mRemovedFromCurrentState = true;
+void Layer::removeRemoteSyncPoints() {
+    for (auto& point : mRemoteSyncPoints) {
+        point->setTransactionApplied();
+    }
+    mRemoteSyncPoints.clear();
 
-    // the layer is removed from SF mCurrentState to mLayersPendingRemoval
-    if (mCurrentState.zOrderRelativeOf != nullptr) {
-        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
-        if (strongRelative != nullptr) {
-            strongRelative->removeZOrderRelative(this);
-            mFlinger->setTransactionFlags(eTraversalNeeded);
+    {
+        Mutex::Autolock pendingStateLock(mPendingStateMutex);
+        for (State pendingState : mPendingStates) {
+            pendingState.barrierLayer_legacy = nullptr;
         }
+    }
+}
+
+void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) {
+    if (mCurrentState.zOrderRelativeOf == nullptr) {
+        return;
+    }
+
+    sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+    if (strongRelative == nullptr) {
+        setZOrderRelativeOf(nullptr);
+        return;
+    }
+
+    if (!std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) {
+        strongRelative->removeZOrderRelative(this);
+        mFlinger->setTransactionFlags(eTraversalNeeded);
         setZOrderRelativeOf(nullptr);
     }
+}
+
+void Layer::removeFromCurrentState() {
+    mRemovedFromCurrentState = true;
 
     // Since we are no longer reachable from CurrentState SurfaceFlinger
     // will no longer invoke doTransaction for us, and so we will
     // never finish applying transactions. We signal the sync point
     // now so that another layer will not become indefinitely
     // blocked.
-    for (auto& point: mRemoteSyncPoints) {
-        point->setTransactionApplied();
-    }
-    mRemoteSyncPoints.clear();
+    removeRemoteSyncPoints();
 
     {
     Mutex::Autolock syncLock(mLocalSyncPointMutex);
@@ -175,13 +194,18 @@
     mLocalSyncPoints.clear();
     }
 
-    for (const auto& child : mCurrentChildren) {
-        child->onRemovedFromCurrentState();
-    }
-
     mFlinger->markLayerPendingRemovalLocked(this);
 }
 
+void Layer::onRemovedFromCurrentState() {
+    auto layersInTree = getLayersInTree(LayerVector::StateSet::Current);
+    std::sort(layersInTree.begin(), layersInTree.end());
+    for (const auto& layer : layersInTree) {
+        layer->removeFromCurrentState();
+        layer->removeRelativeZ(layersInTree);
+    }
+}
+
 void Layer::addToCurrentState() {
     mRemovedFromCurrentState = false;
 
@@ -667,7 +691,7 @@
             // to be applied as per normal (no synchronization).
             mCurrentState.barrierLayer_legacy = nullptr;
         } else {
-            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy);
+            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy, this);
             if (barrierLayer->addSyncPoint(syncPoint)) {
                 mRemoteSyncPoints.push_back(std::move(syncPoint));
             } else {
@@ -1510,6 +1534,7 @@
         if (client != nullptr && parentClient != client) {
             child->mLayerDetached = true;
             child->detachChildren();
+            child->removeRemoteSyncPoints();
         }
     }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3712b2a..6db6beb 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_LAYER_H
 #define ANDROID_LAYER_H
 
-#include <sys/types.h>
-
 #include <compositionengine/LayerFE.h>
 #include <gui/BufferQueue.h>
 #include <gui/ISurfaceComposerClient.h>
@@ -28,6 +26,7 @@
 #include <math/vec4.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/Texture.h>
+#include <sys/types.h>
 #include <ui/FloatRect.h>
 #include <ui/FrameStats.h>
 #include <ui/GraphicBuffer.h>
@@ -44,16 +43,16 @@
 #include <vector>
 
 #include "Client.h"
+#include "ClientCache.h"
+#include "DisplayHardware/ComposerHal.h"
+#include "DisplayHardware/HWComposer.h"
 #include "FrameTracker.h"
 #include "LayerVector.h"
 #include "MonitoredProducer.h"
+#include "RenderArea.h"
 #include "SurfaceFlinger.h"
 #include "TransactionCompletedThread.h"
 
-#include "DisplayHardware/ComposerHal.h"
-#include "DisplayHardware/HWComposer.h"
-#include "RenderArea.h"
-
 using namespace android::surfaceflinger;
 
 namespace android {
@@ -94,7 +93,7 @@
     LayerMetadata metadata;
 };
 
-class Layer : public virtual compositionengine::LayerFE {
+class Layer : public virtual compositionengine::LayerFE, public ClientCache::ErasedRecipient {
     static std::atomic<int32_t> sSequence;
 
 public:
@@ -571,6 +570,17 @@
     virtual bool isBufferLatched() const { return false; }
 
     /*
+     * Remove relative z for the layer if its relative parent is not part of the
+     * provided layer tree.
+     */
+    void removeRelativeZ(const std::vector<Layer*>& layersInTree);
+
+    /*
+     * Remove from current state and mark for removal.
+     */
+    void removeFromCurrentState();
+
+    /*
      * called with the state lock from a binder thread when the layer is
      * removed from the current list to the pending removal list
      */
@@ -690,6 +700,9 @@
     compositionengine::OutputLayer* findOutputLayerForDisplay(
             const sp<const DisplayDevice>& display) const;
 
+    // Inherit from ClientCache::ErasedRecipient
+    void bufferErased(const client_cache_t& /*clientCacheId*/) override {}
+
 protected:
     // constant
     sp<SurfaceFlinger> mFlinger;
@@ -733,8 +746,11 @@
 
     class SyncPoint {
     public:
-        explicit SyncPoint(uint64_t frameNumber)
-              : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+        explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer)
+              : mFrameNumber(frameNumber),
+                mFrameIsAvailable(false),
+                mTransactionIsApplied(false),
+                mRequestedSyncLayer(requestedSyncLayer) {}
 
         uint64_t getFrameNumber() const { return mFrameNumber; }
 
@@ -746,10 +762,13 @@
 
         void setTransactionApplied() { mTransactionIsApplied = true; }
 
+        sp<Layer> getRequestedSyncLayer() { return mRequestedSyncLayer.promote(); }
+
     private:
         const uint64_t mFrameNumber;
         std::atomic<bool> mFrameIsAvailable;
         std::atomic<bool> mTransactionIsApplied;
+        wp<Layer> mRequestedSyncLayer;
     };
 
     // SyncPoints which will be signaled when the correct frame is at the head
@@ -928,6 +947,8 @@
     void setZOrderRelativeOf(const wp<Layer>& relativeOf);
 
     bool mGetHandleCalled = false;
+
+    void removeRemoteSyncPoints();
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 3684260..66906e9 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -26,6 +26,8 @@
 #include <utils/Trace.h>
 #include <string>
 
+#include <compositionengine/Display.h>
+#include <compositionengine/impl/OutputCompositionState.h>
 #include "DisplayDevice.h"
 #include "Layer.h"
 #include "SurfaceFlinger.h"
@@ -264,7 +266,26 @@
 }
 } // anonymous namespace
 
-float sampleArea(const uint32_t* data, int32_t stride, const Rect& area) {
+float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride,
+                 uint32_t orientation, const Rect& sample_area) {
+    if (!sample_area.isValid() || (sample_area.getWidth() > width) ||
+        (sample_area.getHeight() > height)) {
+        ALOGE("invalid sampling region requested");
+        return 0.0f;
+    }
+
+    // (b/133849373) ROT_90 screencap images produced upside down
+    auto area = sample_area;
+    if (orientation & ui::Transform::ROT_90) {
+        area.top = height - area.top;
+        area.bottom = height - area.bottom;
+        std::swap(area.top, area.bottom);
+
+        area.left = width - area.left;
+        area.right = width - area.right;
+        std::swap(area.left, area.right);
+    }
+
     std::array<int32_t, 256> brightnessBuckets = {};
     const int32_t majoritySampleNum = area.getWidth() * area.getHeight() / 2;
 
@@ -293,18 +314,21 @@
 
 std::vector<float> RegionSamplingThread::sampleBuffer(
         const sp<GraphicBuffer>& buffer, const Point& leftTop,
-        const std::vector<RegionSamplingThread::Descriptor>& descriptors) {
+        const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation) {
     void* data_raw = nullptr;
     buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, &data_raw);
     std::shared_ptr<uint32_t> data(reinterpret_cast<uint32_t*>(data_raw),
                                    [&buffer](auto) { buffer->unlock(); });
     if (!data) return {};
 
+    const int32_t width = buffer->getWidth();
+    const int32_t height = buffer->getHeight();
     const int32_t stride = buffer->getStride();
     std::vector<float> lumas(descriptors.size());
     std::transform(descriptors.begin(), descriptors.end(), lumas.begin(),
                    [&](auto const& descriptor) {
-                       return sampleArea(data.get(), stride, descriptor.area - leftTop);
+                       return sampleArea(data.get(), width, height, stride, orientation,
+                                         descriptor.area - leftTop);
                    });
     return lumas;
 }
@@ -317,6 +341,11 @@
         return;
     }
 
+    const auto device = mFlinger.getDefaultDisplayDevice();
+    const auto display = device->getCompositionDisplay();
+    const auto state = display->getState();
+    const auto orientation = static_cast<ui::Transform::orientation_flags>(state.orientation);
+
     std::vector<RegionSamplingThread::Descriptor> descriptors;
     Region sampleRegion;
     for (const auto& [listener, descriptor] : mDescriptors) {
@@ -326,10 +355,28 @@
 
     const Rect sampledArea = sampleRegion.bounds();
 
-    sp<const DisplayDevice> device = mFlinger.getDefaultDisplayDevice();
-    DisplayRenderArea renderArea(device, sampledArea, sampledArea.getWidth(),
-                                 sampledArea.getHeight(), ui::Dataspace::V0_SRGB,
-                                 ui::Transform::ROT_0);
+    auto dx = 0;
+    auto dy = 0;
+    switch (orientation) {
+        case ui::Transform::ROT_90:
+            dx = device->getWidth();
+            break;
+        case ui::Transform::ROT_180:
+            dx = device->getWidth();
+            dy = device->getHeight();
+            break;
+        case ui::Transform::ROT_270:
+            dy = device->getHeight();
+            break;
+        default:
+            break;
+    }
+
+    ui::Transform t(orientation);
+    auto screencapRegion = t.transform(sampleRegion);
+    screencapRegion = screencapRegion.translate(dx, dy);
+    DisplayRenderArea renderArea(device, screencapRegion.bounds(), sampledArea.getWidth(),
+                                 sampledArea.getHeight(), ui::Dataspace::V0_SRGB, orientation);
 
     std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
 
@@ -395,8 +442,8 @@
     }
 
     ALOGV("Sampling %zu descriptors", activeDescriptors.size());
-    std::vector<float> lumas = sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors);
-
+    std::vector<float> lumas =
+            sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors, orientation);
     if (lumas.size() != activeDescriptors.size()) {
         ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(),
               activeDescriptors.size());
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index 08134e6..3c6fcf3 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -37,7 +37,8 @@
 class SurfaceFlinger;
 struct SamplingOffsetCallback;
 
-float sampleArea(const uint32_t* data, int32_t stride, const Rect& area);
+float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride,
+                 uint32_t orientation, const Rect& area);
 
 class RegionSamplingThread : public IBinder::DeathRecipient {
 public:
@@ -94,7 +95,7 @@
     };
     std::vector<float> sampleBuffer(
             const sp<GraphicBuffer>& buffer, const Point& leftTop,
-            const std::vector<RegionSamplingThread::Descriptor>& descriptors);
+            const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation);
 
     void doSample();
     void binderDied(const wp<IBinder>& who) override;
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 95ff9d0..e59d459 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -92,7 +92,6 @@
         mPeriod = period;
         if (!mModelLocked && referenceTimeChanged) {
             for (auto& eventListener : mEventListeners) {
-                eventListener.mHasFired = false;
                 eventListener.mLastEventTime =
                         mReferenceTime - mPeriod + mPhase + eventListener.mPhase;
             }
@@ -123,13 +122,6 @@
 
     void unlockModel() {
         Mutex::Autolock lock(mMutex);
-        if (mModelLocked) {
-            for (auto& eventListener : mEventListeners) {
-                if (eventListener.mLastEventTime > mReferenceTime) {
-                    eventListener.mHasFired = true;
-                }
-            }
-        }
         mModelLocked = false;
         ATRACE_INT("DispSync:ModelLocked", mModelLocked);
     }
@@ -259,10 +251,6 @@
             listener.mLastCallbackTime = lastCallbackTime;
         }
 
-        if (!mModelLocked && listener.mLastEventTime > mReferenceTime) {
-            listener.mHasFired = true;
-        }
-
         mEventListeners.push_back(listener);
 
         mCond.signal();
@@ -305,7 +293,14 @@
                 } else if (diff < -mPeriod / 2) {
                     diff += mPeriod;
                 }
+
+                if (phase < 0 && oldPhase > 0) {
+                    diff += mPeriod;
+                } else if (phase > 0 && oldPhase < 0) {
+                    diff -= mPeriod;
+                }
                 eventListener.mLastEventTime -= diff;
+                eventListener.mLastCallbackTime -= diff;
                 mCond.signal();
                 return NO_ERROR;
             }
@@ -320,7 +315,6 @@
         nsecs_t mLastEventTime;
         nsecs_t mLastCallbackTime;
         DispSync::Callback* mCallback;
-        bool mHasFired = false;
     };
 
     struct CallbackInvocation {
@@ -368,12 +362,7 @@
                           eventListener.mName);
                     continue;
                 }
-                if (eventListener.mHasFired && !mModelLocked) {
-                    eventListener.mLastEventTime = t;
-                    ALOGV("[%s] [%s] Skipping event due to already firing", mName,
-                          eventListener.mName);
-                    continue;
-                }
+
                 CallbackInvocation ci;
                 ci.mCallback = eventListener.mCallback;
                 ci.mEventTime = t;
@@ -382,7 +371,6 @@
                 callbackInvocations.push_back(ci);
                 eventListener.mLastEventTime = t;
                 eventListener.mLastCallbackTime = now;
-                eventListener.mHasFired = true;
             }
         }
 
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 00948ae..265b8aa 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -27,14 +27,16 @@
 
 namespace android {
 
-DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
+DispSyncSource::DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset,
+                               nsecs_t offsetThresholdForNextVsync, 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) {}
+        mPhaseOffset(phaseOffset),
+        mOffsetThresholdForNextVsync(offsetThresholdForNextVsync) {}
 
 void DispSyncSource::setVSyncEnabled(bool enable) {
     std::lock_guard lock(mVsyncMutex);
@@ -64,15 +66,15 @@
 
 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;
+    const nsecs_t period = mDispSync->getPeriod();
+    // Check if offset should be handled as negative
+    if (phaseOffset >= mOffsetThresholdForNextVsync) {
+        phaseOffset -= period;
     }
+
+    // Normalize phaseOffset to [-period, period)
+    const int numPeriods = phaseOffset / period;
+    phaseOffset -= numPeriods * period;
     mPhaseOffset = phaseOffset;
 
     // If we're not enabled, we don't need to mess with the listeners
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 4759699..b6785c5 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -25,7 +25,8 @@
 
 class DispSyncSource final : public VSyncSource, private DispSync::Callback {
 public:
-    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name);
+    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, nsecs_t offsetThresholdForNextVsync,
+                   bool traceVsync, const char* name);
 
     ~DispSyncSource() override = default;
 
@@ -53,6 +54,7 @@
 
     std::mutex mVsyncMutex;
     nsecs_t mPhaseOffset GUARDED_BY(mVsyncMutex);
+    const nsecs_t mOffsetThresholdForNextVsync;
     bool mEnabled GUARDED_BY(mVsyncMutex) = false;
 };
 
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 05bad4d..9d1f777 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -76,6 +76,10 @@
             return StringPrintf("VSync{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
                                 ", count=%u}",
                                 event.header.displayId, event.vsync.count);
+        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+            return StringPrintf("ConfigChanged{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
+                                ", configId=%u}",
+                                event.header.displayId, event.config.configId);
         default:
             return "Event{}";
     }
@@ -107,8 +111,10 @@
 } // namespace
 
 EventThreadConnection::EventThreadConnection(EventThread* eventThread,
-                                             ResyncCallback resyncCallback)
+                                             ResyncCallback resyncCallback,
+                                             ISurfaceComposer::ConfigChanged configChanged)
       : resyncCallback(std::move(resyncCallback)),
+        configChanged(configChanged),
         mEventThread(eventThread),
         mChannel(gui::BitTube::DefaultSize) {}
 
@@ -203,8 +209,10 @@
     mVSyncSource->setPhaseOffset(phaseOffset);
 }
 
-sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
-    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
+sp<EventThreadConnection> EventThread::createEventConnection(
+        ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const {
+    return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
+                                     configChanged);
 }
 
 status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -398,9 +406,11 @@
                                      const sp<EventThreadConnection>& connection) const {
     switch (event.header.type) {
         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
-        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
             return true;
 
+        case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+            return connection->configChanged == ISurfaceComposer::eConfigChangedDispatch;
+
         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
             switch (connection->vsyncRequest) {
                 case VSyncRequest::None:
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 61530c6..dd23b88 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -69,7 +69,8 @@
 
 class EventThreadConnection : public BnDisplayEventConnection {
 public:
-    EventThreadConnection(EventThread*, ResyncCallback);
+    EventThreadConnection(EventThread*, ResyncCallback,
+                          ISurfaceComposer::ConfigChanged configChanged);
     virtual ~EventThreadConnection();
 
     virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -82,6 +83,7 @@
     const ResyncCallback resyncCallback;
 
     VSyncRequest vsyncRequest = VSyncRequest::None;
+    const ISurfaceComposer::ConfigChanged configChanged;
 
 private:
     virtual void onFirstRef();
@@ -93,7 +95,8 @@
 public:
     virtual ~EventThread();
 
-    virtual sp<EventThreadConnection> createEventConnection(ResyncCallback) const = 0;
+    virtual sp<EventThreadConnection> createEventConnection(
+            ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const = 0;
 
     // called before the screen is turned off from main thread
     virtual void onScreenReleased() = 0;
@@ -128,7 +131,8 @@
     EventThread(std::unique_ptr<VSyncSource>, InterceptVSyncsCallback, const char* threadName);
     ~EventThread();
 
-    sp<EventThreadConnection> createEventConnection(ResyncCallback) const override;
+    sp<EventThreadConnection> createEventConnection(
+            ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const override;
 
     status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
     void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 1db43a3..e762af3 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -173,5 +173,18 @@
     }
 }
 
+void LayerHistory::clearHistory() {
+    std::lock_guard lock(mLock);
+
+    auto it = mActiveLayerInfos.begin();
+    while (it != mActiveLayerInfos.end()) {
+        auto id = it->first;
+        auto layerInfo = it->second;
+        layerInfo->clearHistory();
+        mInactiveLayerInfos.insert({id, layerInfo});
+        it = mActiveLayerInfos.erase(it);
+    }
+}
+
 } // namespace scheduler
 } // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index adc5ce5..2569b46 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -64,6 +64,9 @@
     // layers. See go/content-fps-detection-in-scheduler for more information.
     std::pair<float, bool> getDesiredRefreshRateAndHDR();
 
+    // Clears all layer history.
+    void clearHistory();
+
     // Removes the handle and the object from the map.
     void destroyLayer(const int64_t id);
 
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index baf900d..fcb307f 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -96,7 +96,8 @@
     }
 
     mEventThread = eventThread;
-    mEvents = eventThread->createEventConnection(std::move(resyncCallback));
+    mEvents = eventThread->createEventConnection(std::move(resyncCallback),
+                                                 ISurfaceComposer::eConfigChangedSuppress);
     mEvents->stealReceiveChannel(&mEventTube);
     mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                    this);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 1d899df..bb24f73 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -119,17 +119,19 @@
 }
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
-        const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
+        const char* connectionName, nsecs_t phaseOffsetNs, nsecs_t offsetThresholdForNextVsync,
+        ResyncCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const int64_t id = sNextId++;
     ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
 
     std::unique_ptr<EventThread> eventThread =
             makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
-                            std::move(interceptCallback));
+                            offsetThresholdForNextVsync, std::move(interceptCallback));
 
     auto eventThreadConnection =
-            createConnectionInternal(eventThread.get(), std::move(resyncCallback));
+            createConnectionInternal(eventThread.get(), std::move(resyncCallback),
+                                     ISurfaceComposer::eConfigChangedSuppress);
     mConnections.emplace(id,
                          std::make_unique<Connection>(new ConnectionHandle(id),
                                                       eventThreadConnection,
@@ -138,24 +140,28 @@
 }
 
 std::unique_ptr<EventThread> Scheduler::makeEventThread(
-        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
+        nsecs_t offsetThresholdForNextVsync,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     std::unique_ptr<VSyncSource> eventThreadSource =
-            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
+            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, offsetThresholdForNextVsync,
+                                             true, connectionName);
     return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
                                                std::move(interceptCallback), connectionName);
 }
 
-sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread,
-                                                              ResyncCallback&& resyncCallback) {
-    return eventThread->createEventConnection(std::move(resyncCallback));
+sp<EventThreadConnection> Scheduler::createConnectionInternal(
+        EventThread* eventThread, ResyncCallback&& resyncCallback,
+        ISurfaceComposer::ConfigChanged configChanged) {
+    return eventThread->createEventConnection(std::move(resyncCallback), configChanged);
 }
 
 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
-        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
+        const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback,
+        ISurfaceComposer::ConfigChanged configChanged) {
     RETURN_VALUE_IF_INVALID(nullptr);
     return createConnectionInternal(mConnections[handle->id]->thread.get(),
-                                    std::move(resyncCallback));
+                                    std::move(resyncCallback), configChanged);
 }
 
 EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
@@ -404,6 +410,10 @@
     if (mSupportKernelTimer) {
         resetIdleTimer();
     }
+
+    // Touch event will boost the refresh rate to performance.
+    // Clear Layer History to get fresh FPS detection
+    mLayerHistory.clearHistory();
 }
 
 void Scheduler::resetTimerCallback() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index a32bd41..eaad37c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -96,12 +96,13 @@
     virtual ~Scheduler();
 
     /** Creates an EventThread connection. */
-    sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs,
-                                          ResyncCallback,
+    sp<ConnectionHandle> createConnection(const char* connectionName, nsecs_t phaseOffsetNs,
+                                          nsecs_t offsetThresholdForNextVsync, ResyncCallback,
                                           impl::EventThread::InterceptVSyncsCallback);
 
-    sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
-                                                             ResyncCallback);
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            const sp<ConnectionHandle>& handle, ResyncCallback,
+            ISurfaceComposer::ConfigChanged configChanged);
 
     // Getter methods.
     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -184,7 +185,8 @@
 
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
-            const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            const char* connectionName, DispSync* dispSync, nsecs_t phaseOffsetNs,
+            nsecs_t offsetThresholdForNextVsync,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
 private:
@@ -197,7 +199,8 @@
     enum class TouchState { INACTIVE, ACTIVE };
 
     // Creates a connection on the given EventThread and forwards the given callbacks.
-    sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&);
+    sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
+                                                       ISurfaceComposer::ConfigChanged);
 
     nsecs_t calculateAverage() const;
     void updateFrameSkipping(const int64_t skipCount);
@@ -297,7 +300,7 @@
     const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
 
     // Global config to force HDR content to work on DEFAULT refreshRate
-    static constexpr bool mForceHDRContentToDefaultRefreshRate = true;
+    static constexpr bool mForceHDRContentToDefaultRefreshRate = false;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 41c3a3a..73a1fb9 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -56,10 +56,12 @@
     // appEarly: Like sfEarly, but for the app-vsync
     // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
     // appLate: The regular app vsync phase offset.
-    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late) {
+    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
+                         nsecs_t thresholdForNextVsync) {
         mEarlyOffsets = early;
         mEarlyGlOffsets = earlyGl;
         mLateOffsets = late;
+        mThresholdForNextVsync = thresholdForNextVsync;
 
         if (mSfConnectionHandle && late.sf != mOffsets.load().sf) {
             mScheduler->setPhaseOffset(mSfConnectionHandle, late.sf);
@@ -192,6 +194,7 @@
     Offsets mLateOffsets;
     Offsets mEarlyOffsets;
     Offsets mEarlyGlOffsets;
+    nsecs_t mThresholdForNextVsync;
 
     EventThread* mSfEventThread = nullptr;
     EventThread* mAppEventThread = nullptr;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cd4f69a..a96305e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -377,7 +377,8 @@
     mLumaSampling = atoi(value);
 
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late);
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
 
     // We should be reading 'persist.sys.sf.color_saturation' here
     // but since /data may be encrypted, we need to wait until after vold
@@ -616,13 +617,16 @@
             mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
 
     mAppConnectionHandle =
-            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
+            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
+                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                          resyncCallback,
                                          impl::EventThread::InterceptVSyncsCallback());
-    mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
-                                                       resyncCallback, [this](nsecs_t timestamp) {
-                                                           mInterceptor->saveVSyncEvent(timestamp);
-                                                       });
+    mSfConnectionHandle =
+            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
+                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
+                                         resyncCallback, [this](nsecs_t timestamp) {
+                                             mInterceptor->saveVSyncEvent(timestamp);
+                                         });
 
     mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
     mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
@@ -940,7 +944,8 @@
         mVsyncModulator.onRefreshRateChangeInitiated();
         mPhaseOffsets->setRefreshRateType(info.type);
         const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-        mVsyncModulator.setPhaseOffsets(early, gl, late);
+        mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                        mPhaseOffsets->getOffsetThresholdForNextVsync());
     }
     mDesiredActiveConfigChanged = true;
     ATRACE_INT("DesiredActiveConfigChanged", mDesiredActiveConfigChanged);
@@ -974,7 +979,8 @@
 
     mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late);
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
     ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
 
     if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
@@ -992,7 +998,8 @@
     mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
     mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type);
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
-    mVsyncModulator.setPhaseOffsets(early, gl, late);
+    mVsyncModulator.setPhaseOffsets(early, gl, late,
+                                    mPhaseOffsets->getOffsetThresholdForNextVsync());
 }
 
 bool SurfaceFlinger::performSetActiveConfig() {
@@ -1372,7 +1379,7 @@
 // ----------------------------------------------------------------------------
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
-        ISurfaceComposer::VsyncSource vsyncSource) {
+        ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) {
     auto resyncCallback = mScheduler->makeResyncCallback([this] {
         Mutex::Autolock lock(mStateLock);
         return getVsyncPeriod();
@@ -1381,7 +1388,8 @@
     const auto& handle =
             vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
 
-    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
+    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback),
+                                                    configChanged);
 }
 
 // ----------------------------------------------------------------------------
@@ -1530,10 +1538,23 @@
 
 void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {
     ATRACE_CALL();
-    Mutex::Autolock lock(mStateLock);
+
+    // Enable / Disable HWVsync from the main thread to avoid race conditions with
+    // display power state.
+    postMessageAsync(new LambdaMessage(
+            [=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
+}
+
+void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
+    ATRACE_CALL();
+
+    mHWCVsyncPendingState = enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable;
+
     if (const auto displayId = getInternalDisplayIdLocked()) {
-        getHwComposer().setVsyncEnabled(*displayId,
-                                        enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
+        sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
+        if (display && display->isPoweredOn()) {
+            setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
+        }
     }
 }
 
@@ -2151,7 +2172,14 @@
     }
 
     mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
-    mTransactionCompletedThread.sendCallbacks();
+
+    // Lock the mStateLock in case SurfaceFlinger is in the middle of applying a transaction.
+    // If we do not lock here, a callback could be sent without all of its SurfaceControls and
+    // metrics.
+    {
+        Mutex::Autolock _l(mStateLock);
+        mTransactionCompletedThread.sendCallbacks();
+    }
 
     if (mLumaSampling && mRegionSamplingThread) {
         mRegionSamplingThread->notifyNewContent();
@@ -4133,6 +4161,9 @@
     sp<GraphicBuffer> buffer;
     if (bufferChanged && cacheIdChanged) {
         ClientCache::getInstance().add(s.cachedBuffer, s.buffer);
+        ClientCache::getInstance().registerErasedRecipient(s.cachedBuffer,
+                                                           wp<ClientCache::ErasedRecipient>(layer));
+        getRenderEngine().cacheExternalTextureBuffer(s.buffer);
         buffer = s.buffer;
     } else if (cacheIdChanged) {
         buffer = ClientCache::getInstance().get(s.cachedBuffer);
@@ -4416,6 +4447,13 @@
             new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
 }
 
+void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled) {
+    if (mHWCVsyncState != enabled) {
+        getHwComposer().setVsyncEnabled(displayId, enabled);
+        mHWCVsyncState = enabled;
+    }
+}
+
 void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode) {
     if (display->isVirtual()) {
         ALOGE("%s: Invalid operation on virtual display", __FUNCTION__);
@@ -4442,6 +4480,7 @@
         // Turn on the display
         getHwComposer().setPowerMode(*displayId, mode);
         if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
+            setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
             mScheduler->onScreenAcquired(mAppConnectionHandle);
             mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
         }
@@ -4467,6 +4506,9 @@
             mScheduler->onScreenReleased(mAppConnectionHandle);
         }
 
+        // Make sure HWVsync is disabled before turning off the display
+        setVsyncEnabledInHWC(*displayId, HWC2::Vsync::Disable);
+
         getHwComposer().setPowerMode(*displayId, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3d98ec1..6d4b2d7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -293,6 +293,9 @@
     // TODO: this should be made accessible only to EventThread
     void setPrimaryVsyncEnabled(bool enabled);
 
+    // main thread function to enable/disable h/w composer event
+    void setPrimaryVsyncEnabledInternal(bool enabled);
+
     // called on the main thread by MessageQueue when an internal message
     // is received
     // TODO: this should be made accessible only to MessageQueue
@@ -404,7 +407,9 @@
             const sp<IGraphicBufferProducer>& bufferProducer) const override;
     status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
     sp<IDisplayEventConnection> createDisplayEventConnection(
-            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp) override;
+            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp,
+            ISurfaceComposer::ConfigChanged configChanged =
+                    ISurfaceComposer::eConfigChangedSuppress) override;
     status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
             bool& outCapturedSecureLayers, const ui::Dataspace reqDataspace,
             const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
@@ -840,6 +845,7 @@
     }
 
     bool previousFrameMissed();
+    void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
 
     /*
      * Debugging & dumpsys
@@ -1173,6 +1179,10 @@
     // The Layer pointer is removed from the set when the destructor is called so there shouldn't
     // be any issues with a raw pointer referencing an invalid object.
     std::unordered_set<Layer*> mOffscreenLayers;
+
+    // Flags to capture the state of Vsync in HWC
+    HWC2::Vsync mHWCVsyncState = HWC2::Vsync::Disable;
+    HWC2::Vsync mHWCVsyncPendingState = HWC2::Vsync::Disable;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 5ebae1e..6b4634a 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*"
+            "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*:RelativeZTest.*"
         }
 }
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index ec1ac4b..f83b3ea 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -385,6 +385,18 @@
         return createLayer(mClient, name, width, height, flags, parent);
     }
 
+    sp<SurfaceControl> createColorLayer(const char* name, const Color& color,
+                                        SurfaceControl* parent = nullptr) {
+        auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */,
+                                        PIXEL_FORMAT_RGBA_8888,
+                                        ISurfaceComposerClient::eFXSurfaceColor, parent);
+        asTransaction([&](Transaction& t) {
+            t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f});
+            t.setAlpha(colorLayer, color.a / 255.0f);
+        });
+        return colorLayer;
+    }
+
     ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
         // wait for previous transactions (such as setSize) to complete
         Transaction().apply(true);
@@ -4725,6 +4737,48 @@
         mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED);
     }
 }
+TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) {
+    sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+    sp<SurfaceControl> childNewClient =
+            newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
+                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+    ASSERT_TRUE(childNewClient != nullptr);
+    ASSERT_TRUE(childNewClient->isValid());
+
+    fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+
+    Transaction()
+            .hide(mChild)
+            .show(childNewClient)
+            .setPosition(childNewClient, 10, 10)
+            .setPosition(mFGSurfaceControl, 64, 64)
+            .apply();
+
+    {
+        mCapture = screenshot();
+        Rect rect = Rect(74, 74, 84, 84);
+        mCapture->expectBorder(rect, Color{195, 63, 63, 255});
+        mCapture->expectColor(rect, Color{200, 200, 200, 255});
+    }
+
+    Transaction()
+            .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(),
+                                          mFGSurfaceControl->getSurface()->getNextFrameNumber())
+            .apply();
+    Transaction().detachChildren(mFGSurfaceControl).apply();
+    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32));
+
+    // BufferLayer can still dequeue buffers even though there's a detached layer with a
+    // deferred transaction.
+    {
+        SCOPED_TRACE("new buffer");
+        mCapture = screenshot();
+        Rect rect = Rect(74, 74, 84, 84);
+        mCapture->expectBorder(rect, Color::RED);
+        mCapture->expectColor(rect, Color{200, 200, 200, 255});
+    }
+}
 
 TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
     asTransaction([&](Transaction& t) {
@@ -5833,4 +5887,126 @@
                 allowedConfigs.end());
 }
 
+class RelativeZTest : public LayerTransactionTest {
+protected:
+    virtual void SetUp() {
+        LayerTransactionTest::SetUp();
+        ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+        const auto display = SurfaceComposerClient::getInternalDisplayToken();
+        ASSERT_FALSE(display == nullptr);
+
+        // Back layer
+        mBackgroundLayer = createColorLayer("Background layer", Color::RED);
+
+        // Front layer
+        mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN);
+
+        asTransaction([&](Transaction& t) {
+            t.setDisplayLayerStack(display, 0);
+            t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer);
+            t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer);
+        });
+    }
+
+    virtual void TearDown() {
+        LayerTransactionTest::TearDown();
+        mBackgroundLayer = 0;
+        mForegroundLayer = 0;
+    }
+
+    sp<SurfaceControl> mBackgroundLayer;
+    sp<SurfaceControl> mForegroundLayer;
+};
+
+// When a layer is reparented offscreen, remove relative z order if the relative parent
+// is still onscreen so that the layer is not drawn.
+TEST_F(RelativeZTest, LayerRemoved) {
+    std::unique_ptr<ScreenCapture> sc;
+
+    // Background layer (RED)
+    //   Child layer (WHITE) (relative to foregroud layer)
+    // Foregroud layer (GREEN)
+    sp<SurfaceControl> childLayer =
+            createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get());
+
+    Transaction{}
+            .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1)
+            .show(childLayer)
+            .apply();
+
+    {
+        // The childLayer should be in front of the FG control.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+    }
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    Transaction{}.reparent(childLayer, nullptr).apply();
+
+    // Background layer (RED)
+    //   Child layer (WHITE)
+    // Foregroud layer (GREEN)
+    Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply();
+
+    {
+        // The relative z info for child layer should be reset, leaving FG control on top.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+    }
+}
+
+// When a layer is reparented offscreen, preseve relative z order if the relative parent
+// is also offscreen. Regression test b/132613412
+TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) {
+    std::unique_ptr<ScreenCapture> sc;
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   child level 1 (WHITE)
+    //     child level 2a (BLUE)
+    //       child level 3 (GREEN) (relative to child level 2b)
+    //     child level 2b (BLACK)
+    sp<SurfaceControl> childLevel1 =
+            createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get());
+    sp<SurfaceControl> childLevel2a =
+            createColorLayer("child level 2a", Color::BLUE, childLevel1.get());
+    sp<SurfaceControl> childLevel2b =
+            createColorLayer("child level 2b", Color::BLACK, childLevel1.get());
+    sp<SurfaceControl> childLevel3 =
+            createColorLayer("child level 3", Color::GREEN, childLevel2a.get());
+
+    Transaction{}
+            .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1)
+            .show(childLevel2a)
+            .show(childLevel2b)
+            .show(childLevel3)
+            .apply();
+
+    {
+        // The childLevel3 should be in front of childLevel2b.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+    }
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    Transaction{}.reparent(childLevel1, nullptr).apply();
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   child level 1 (WHITE)
+    //     child level 2 back (BLUE)
+    //       child level 3 (GREEN) (relative to child level 2b)
+    //     child level 2 front (BLACK)
+    Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply();
+
+    {
+        // Nothing should change at this point since relative z info was preserved.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+    }
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
index 2e705da..0aa8cf5 100644
--- a/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DispSyncSourceTest.cpp
@@ -51,6 +51,7 @@
     AsyncCallRecorder<void (*)(nsecs_t)> mVSyncEventCallRecorder;
 
     static constexpr std::chrono::nanoseconds mPhaseOffset = 6ms;
+    static constexpr std::chrono::nanoseconds mOffsetThresholdForNextVsync = 16ms;
     static constexpr int mIterations = 100;
 };
 
@@ -78,7 +79,8 @@
 
 void DispSyncSourceTest::createDispSyncSource() {
     createDispSync();
-    mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(), true,
+    mDispSyncSource = std::make_unique<DispSyncSource>(mDispSync.get(), mPhaseOffset.count(),
+                                                       mOffsetThresholdForNextVsync.count(), true,
                                                        "DispSyncSourceTest");
     mDispSyncSource->setCallback(this);
 }
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index ea908a9..dbd9b84 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -55,8 +55,9 @@
     class MockEventThreadConnection : public EventThreadConnection {
     public:
         MockEventThreadConnection(android::impl::EventThread* eventThread,
-                                  ResyncCallback&& resyncCallback)
-              : EventThreadConnection(eventThread, std::move(resyncCallback)) {}
+                                  ResyncCallback&& resyncCallback,
+                                  ISurfaceComposer::ConfigChanged configChanged)
+              : EventThreadConnection(eventThread, std::move(resyncCallback), configChanged) {}
         MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
     };
 
@@ -67,7 +68,8 @@
     ~EventThreadTest() override;
 
     void createThread();
-    sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder);
+    sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder,
+                                                   ISurfaceComposer::ConfigChanged configChanged);
 
     void expectVSyncSetEnabledCallReceived(bool expectedState);
     void expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset);
@@ -110,7 +112,8 @@
             .WillRepeatedly(Invoke(mVSyncSetPhaseOffsetCallRecorder.getInvocable()));
 
     createThread();
-    mConnection = createConnection(mConnectionEventCallRecorder);
+    mConnection = createConnection(mConnectionEventCallRecorder,
+                                   ISurfaceComposer::eConfigChangedDispatch);
 
     // A display must be connected for VSYNC events to be delivered.
     mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
@@ -138,9 +141,10 @@
 }
 
 sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
-        ConnectionEventRecorder& recorder) {
+        ConnectionEventRecorder& recorder, ISurfaceComposer::ConfigChanged configChanged) {
     sp<MockEventThreadConnection> connection =
-            new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable());
+            new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable(),
+                                          configChanged);
     EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
     return connection;
 }
@@ -267,7 +271,9 @@
 TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
     // Create a first connection, register it, and request a vsync rate of zero.
     ConnectionEventRecorder firstConnectionEventRecorder{0};
-    sp<MockEventThreadConnection> firstConnection = createConnection(firstConnectionEventRecorder);
+    sp<MockEventThreadConnection> firstConnection =
+            createConnection(firstConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(0, firstConnection);
 
     // By itself, this should not enable vsync events
@@ -277,7 +283,8 @@
     // However if there is another connection which wants events at a nonzero rate.....
     ConnectionEventRecorder secondConnectionEventRecorder{0};
     sp<MockEventThreadConnection> secondConnection =
-            createConnection(secondConnectionEventRecorder);
+            createConnection(secondConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, secondConnection);
 
     // EventThread should enable vsync callbacks.
@@ -363,7 +370,9 @@
 
 TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) {
     ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
-    sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
+    sp<MockEventThreadConnection> errorConnection =
+            createConnection(errorConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, errorConnection);
 
     // EventThread should enable vsync callbacks.
@@ -387,7 +396,9 @@
 
 TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) {
     ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK};
-    sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
+    sp<MockEventThreadConnection> errorConnection =
+            createConnection(errorConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
     mThread->setVsyncRate(1, errorConnection);
 
     // EventThread should enable vsync callbacks.
@@ -449,5 +460,18 @@
     expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7);
 }
 
+TEST_F(EventThreadTest, suppressConfigChanged) {
+    ConnectionEventRecorder suppressConnectionEventRecorder{0};
+    sp<MockEventThreadConnection> suppressConnection =
+            createConnection(suppressConnectionEventRecorder,
+                             ISurfaceComposer::eConfigChangedSuppress);
+
+    mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 9);
+    expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9);
+
+    auto args = suppressConnectionEventRecorder.waitForCall();
+    ASSERT_FALSE(args.has_value());
+}
+
 } // namespace
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
index 51d6d7e..160f041 100644
--- a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
@@ -17,6 +17,8 @@
 #undef LOG_TAG
 #define LOG_TAG "RegionSamplingTest"
 
+#include <ui/Transform.h>
+
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <array>
@@ -33,18 +35,21 @@
     static int constexpr kWidth = 98;
     static int constexpr kStride = 100;
     static int constexpr kHeight = 29;
+    static int constexpr kOrientation = ui::Transform::ROT_0;
     std::array<uint32_t, kHeight * kStride> buffer;
     Rect const whole_area{0, 0, kWidth, kHeight};
 };
 
 TEST_F(RegionSamplingTest, calculate_mean_white) {
     std::fill(buffer.begin(), buffer.end(), kWhite);
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatEq(1.0f));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatEq(1.0f));
 }
 
 TEST_F(RegionSamplingTest, calculate_mean_black) {
     std::fill(buffer.begin(), buffer.end(), kBlack);
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatEq(0.0f));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatEq(0.0f));
 }
 
 TEST_F(RegionSamplingTest, calculate_mean_partial_region) {
@@ -54,7 +59,8 @@
                                  whole_area.top + halfway_down};
     std::fill(buffer.begin(), buffer.begin() + half, 0);
     std::fill(buffer.begin() + half, buffer.end(), kWhite);
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, partial_region), testing::FloatEq(0.0f));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, partial_region),
+                testing::FloatEq(0.0f));
 }
 
 TEST_F(RegionSamplingTest, calculate_mean_mixed_values) {
@@ -63,15 +69,71 @@
         n++;
         return pixel;
     });
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatNear(0.083f, 0.01f));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatNear(0.083f, 0.01f));
 }
 
 TEST_F(RegionSamplingTest, bimodal_tiebreaker) {
     std::generate(buffer.begin(), buffer.end(),
                   [n = 0]() mutable { return (n++ % 2) ? kBlack : kWhite; });
     // presently there's no tiebreaking strategy in place, accept either of the means
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area),
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
                 testing::AnyOf(testing::FloatEq(1.0), testing::FloatEq(0.0f)));
 }
 
+TEST_F(RegionSamplingTest, bounds_checking) {
+    std::generate(buffer.begin(), buffer.end(),
+                  [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
+
+    Rect invalid_region{0, 0, 4, kHeight + 1};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{0, 0, -4, kHeight};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{3, 0, 2, 0};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{0, 3, 0, 2};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+}
+
+// workaround for b/133849373
+TEST_F(RegionSamplingTest, orientation_90) {
+    std::generate(buffer.begin(), buffer.end(),
+                  [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
+
+    Rect tl_region{0, 0, 4, 4};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
+                           tl_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
+                           tl_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
+                           tl_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
+                           tl_region),
+                testing::Eq(0.0));
+
+    Rect br_region{kWidth - 4, kHeight - 4, kWidth, kHeight};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
+                           br_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
+                           br_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
+                           br_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
+                           br_region),
+                testing::Eq(1.0));
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 1f8b111..740115e 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -25,7 +25,8 @@
     class MockEventThreadConnection : public android::EventThreadConnection {
     public:
         explicit MockEventThreadConnection(EventThread* eventThread)
-              : EventThreadConnection(eventThread, ResyncCallback()) {}
+              : EventThreadConnection(eventThread, ResyncCallback(),
+                                      ISurfaceComposer::eConfigChangedSuppress) {}
         ~MockEventThreadConnection() = default;
 
         MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -47,7 +48,7 @@
 
         std::unique_ptr<EventThread> makeEventThread(
                 const char* /* connectionName */, DispSync* /* dispSync */,
-                nsecs_t /* phaseOffsetNs */,
+                nsecs_t /* phaseOffsetNs */, nsecs_t /* offsetThresholdForNextVsync */,
                 impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
             return std::move(mEventThread);
         }
@@ -81,10 +82,10 @@
 
     // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
     // sure that call gets executed and returns an EventThread::Connection object.
-    EXPECT_CALL(*mEventThread, createEventConnection(_))
+    EXPECT_CALL(*mEventThread, createEventConnection(_, _))
             .WillRepeatedly(Return(mEventThreadConnection));
 
-    mConnectionHandle = mScheduler->createConnection("appConnection", 16, ResyncCallback(),
+    mConnectionHandle = mScheduler->createConnection("appConnection", 16, 16, ResyncCallback(),
                                                      impl::EventThread::InterceptVSyncsCallback());
     EXPECT_TRUE(mConnectionHandle != nullptr);
 }
@@ -105,7 +106,10 @@
     // exceptions, just gracefully continues.
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
-            returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback()));
+            returnedValue =
+                    mScheduler->createDisplayEventConnection(nullptr, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
@@ -126,7 +130,9 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback()));
+                    mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
@@ -155,7 +161,9 @@
     sp<IDisplayEventConnection> returnedValue;
     ASSERT_NO_FATAL_FAILURE(
             returnedValue =
-                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback()));
+                    mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback(),
+                                                             ISurfaceComposer::
+                                                                     eConfigChangedSuppress));
     EXPECT_TRUE(returnedValue != nullptr);
     ASSERT_EQ(returnedValue, mEventThreadConnection);
 
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index c3d2b8d..cb6980e 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <gmock/gmock.h>
+#include <gui/ISurfaceComposer.h>
 
 #include "Scheduler/EventThread.h"
 #include "Scheduler/RefreshRateConfigs.h"
@@ -34,7 +35,8 @@
     // Scheduler::Connection. This allows plugging in mock::EventThread.
     sp<Scheduler::ConnectionHandle> addConnection(std::unique_ptr<EventThread> eventThread) {
         sp<EventThreadConnection> eventThreadConnection =
-                new EventThreadConnection(eventThread.get(), ResyncCallback());
+                new EventThreadConnection(eventThread.get(), ResyncCallback(),
+                                          ISurfaceComposer::eConfigChangedSuppress);
         const int64_t id = sNextId++;
         mConnections.emplace(id,
                              std::make_unique<Scheduler::Connection>(new ConnectionHandle(id),
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 5b5f8e7..ed35ebf 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,7 +28,8 @@
     EventThread();
     ~EventThread() override;
 
-    MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback));
+    MOCK_CONST_METHOD2(createEventConnection,
+                       sp<EventThreadConnection>(ResyncCallback, ISurfaceComposer::ConfigChanged));
     MOCK_METHOD0(onScreenReleased, void());
     MOCK_METHOD0(onScreenAcquired, void());
     MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));