Merge "Fix brightness change during rotation when playing HDR videos." into tm-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 890c15f..2b94b71 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1648,7 +1648,7 @@
 
     DumpPacketStats();
 
-    RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
+    RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
 
     DoKmsg();
 
@@ -2084,7 +2084,7 @@
     int timeout_failures = 0;
     bool dalvik_found = false;
 
-    const std::set<int> hal_pids = get_interesting_hal_pids();
+    const std::set<int> hal_pids = get_interesting_pids();
 
     struct dirent* d;
     while ((d = readdir(proc.get()))) {
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 49c1318..f0c19b9 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -65,6 +65,7 @@
                                              const sp<LocalRegistrationCallback>&));
     MOCK_METHOD2(unregisterForNotifications, status_t(const String16&,
                                              const sp<LocalRegistrationCallback>&));
+    MOCK_METHOD0(getServiceDebugInfo, std::vector<ServiceDebugInfo>());
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
 };
diff --git a/headers/media_plugin/media/openmax/OMX_IndexExt.h b/headers/media_plugin/media/openmax/OMX_IndexExt.h
index 07bd749..0af40dd 100644
--- a/headers/media_plugin/media/openmax/OMX_IndexExt.h
+++ b/headers/media_plugin/media/openmax/OMX_IndexExt.h
@@ -104,6 +104,7 @@
     OMX_IndexConfigLatency,                         /**< reference: OMX_PARAM_U32TYPE */
     OMX_IndexConfigLowLatency,                      /**< reference: OMX_CONFIG_BOOLEANTYPE */
     OMX_IndexConfigAndroidTunnelPeek,               /**< reference: OMX_CONFIG_BOOLEANTYPE */
+    OMX_IndexConfigAndroidTunnelPeekLegacyMode,     /**< reference: OMX_CONFIG_BOOLEANTYPE */
     OMX_IndexExtOtherEndUnused,
 
     /* Time configurations */
diff --git a/include/input/PrintTools.h b/include/input/PrintTools.h
index 7c3b29b..0a75278 100644
--- a/include/input/PrintTools.h
+++ b/include/input/PrintTools.h
@@ -58,4 +58,13 @@
 
 const char* toString(bool value);
 
+/**
+ * Add "prefix" to the beginning of each line in the provided string
+ * "str".
+ * The string 'str' is typically multi-line.
+ * The most common use case for this function is to add some padding
+ * when dumping state.
+ */
+std::string addLinePrefix(std::string str, const std::string& prefix);
+
 } // namespace android
\ No newline at end of file
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 63d87da..d8d2cf2 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -226,6 +226,10 @@
     ],
 
     afdo: true,
+
+    header_abi_checker: {
+        diff_flags: ["-allow-adding-removing-weak-symbols"],
+    },
 }
 
 cc_defaults {
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index ea2f8d2..fd2d868 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -99,6 +99,8 @@
 
     status_t unregisterForNotifications(const String16& service,
                                         const sp<AidlRegistrationCallback>& cb) override;
+
+    std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override;
     // for legacy ABI
     const String16& getInterfaceDescriptor() const override {
         return mTheRealServiceManager->getInterfaceDescriptor();
@@ -543,6 +545,23 @@
     return OK;
 }
 
+std::vector<IServiceManager::ServiceDebugInfo> ServiceManagerShim::getServiceDebugInfo() {
+    std::vector<os::ServiceDebugInfo> serviceDebugInfos;
+    std::vector<IServiceManager::ServiceDebugInfo> ret;
+    if (Status status = mTheRealServiceManager->getServiceDebugInfo(&serviceDebugInfos);
+        !status.isOk()) {
+        ALOGW("%s Failed to get ServiceDebugInfo", __FUNCTION__);
+        return ret;
+    }
+    for (const auto& serviceDebugInfo : serviceDebugInfos) {
+        IServiceManager::ServiceDebugInfo retInfo;
+        retInfo.pid = serviceDebugInfo.debugPid;
+        retInfo.name = serviceDebugInfo.name;
+        ret.emplace_back(retInfo);
+    }
+    return ret;
+}
+
 #ifndef __ANDROID__
 // ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API.
 // The internal implementation of the AIDL interface android::os::IServiceManager calls into
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index bb55831..413c97f 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -134,6 +134,12 @@
 
     virtual status_t unregisterForNotifications(const String16& name,
                                                 const sp<LocalRegistrationCallback>& callback) = 0;
+
+    struct ServiceDebugInfo {
+        std::string name;
+        int pid;
+    };
+    virtual std::vector<ServiceDebugInfo> getServiceDebugInfo() = 0;
 };
 
 sp<IServiceManager> defaultServiceManager();
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index acda402..09fbdea 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -26,6 +26,7 @@
 
     shared_libs: [
         "libbase",
+        "libbinder",
         "libhidlbase",
         "liblog",
         "libutils",
@@ -33,7 +34,10 @@
 
     srcs: ["dump_utils.cpp"],
 
-    cflags: ["-Wall", "-Werror"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
 
     export_include_dirs: [
         "include",
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 29c788b..0f1a02a 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -20,6 +20,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
+#include <binder/IServiceManager.h>
 #include <dumputils/dump_utils.h>
 #include <log/log.h>
 
@@ -52,8 +53,8 @@
         NULL,
 };
 
-/* list of hal interface to dump containing process during native dumps */
-static const char* hal_interfaces_to_dump[] {
+/* list of hidl hal interface to dump containing process during native dumps */
+static const char* hidl_hal_interfaces_to_dump[] {
         "android.hardware.audio@4.0::IDevicesFactory",
         "android.hardware.audio@5.0::IDevicesFactory",
         "android.hardware.audio@6.0::IDevicesFactory",
@@ -82,6 +83,11 @@
         NULL,
 };
 
+/* list of hal interface to dump containing process during native dumps */
+static const std::vector<std::string> aidl_interfaces_to_dump {
+        "android.hardware.camera.provider.ICameraProvider",
+};
+
 /* list of extra hal interfaces to dump containing process during native dumps */
 // This is filled when dumpstate is called.
 static std::set<const std::string> extra_hal_interfaces_to_dump;
@@ -104,7 +110,7 @@
 
 // check if interface is included in either default hal list or extra hal list
 bool should_dump_hal_interface(const std::string& interface) {
-    for (const char** i = hal_interfaces_to_dump; *i; i++) {
+    for (const char** i = hidl_hal_interfaces_to_dump; *i; i++) {
         if (interface == *i) {
             return true;
         }
@@ -130,14 +136,26 @@
     return false;
 }
 
-std::set<int> get_interesting_hal_pids() {
+static void get_interesting_aidl_pids(std::set<int> &pids) {
+    using ServiceDebugInfo = android::IServiceManager::ServiceDebugInfo;
+    auto sm = android::defaultServiceManager();
+    std::vector<ServiceDebugInfo> serviceDebugInfos = sm->getServiceDebugInfo();
+    for (const auto & serviceDebugInfo : serviceDebugInfos) {
+        for (const auto &aidl_prefix : aidl_interfaces_to_dump) {
+            // Check for prefix match with aidl interface to dump
+            if (serviceDebugInfo.name.rfind(aidl_prefix, 0) == 0) {
+                pids.insert(serviceDebugInfo.pid);
+            }
+        }
+    }
+}
+
+static void get_interesting_hidl_pids(std::set<int> &pids) {
     using android::hidl::manager::V1_0::IServiceManager;
     using android::sp;
     using android::hardware::Return;
 
     sp<IServiceManager> manager = IServiceManager::getService();
-    std::set<int> pids;
-
     read_extra_hals_to_dump_from_property();
 
     Return<void> ret = manager->debugDump([&](auto& hals) {
@@ -146,11 +164,9 @@
                 continue;
             }
 
-            if (!should_dump_hal_interface(info.interfaceName)) {
-                continue;
+            if (should_dump_hal_interface(info.interfaceName)) {
+                pids.insert(info.pid);
             }
-
-            pids.insert(info.pid);
         }
     });
 
@@ -158,7 +174,14 @@
         ALOGE("Could not get list of HAL PIDs: %s\n", ret.description().c_str());
     }
 
-    return pids; // whether it was okay or not
+    return;
+}
+
+std::set<int> get_interesting_pids() {
+    std::set<int> interesting_pids;
+    get_interesting_hidl_pids(interesting_pids);
+    get_interesting_aidl_pids(interesting_pids);
+    return interesting_pids;
 }
 
 bool IsZygote(int pid) {
diff --git a/libs/dumputils/include/dumputils/dump_utils.h b/libs/dumputils/include/dumputils/dump_utils.h
index 25f7127..7c5329d 100644
--- a/libs/dumputils/include/dumputils/dump_utils.h
+++ b/libs/dumputils/include/dumputils/dump_utils.h
@@ -21,7 +21,7 @@
 
 bool should_dump_native_traces(const char* path);
 
-std::set<int> get_interesting_hal_pids();
+std::set<int> get_interesting_pids();
 
 bool IsZygote(int pid);
 
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp
index 61e4a98..6c6d7f3 100644
--- a/libs/fakeservicemanager/ServiceManager.cpp
+++ b/libs/fakeservicemanager/ServiceManager.cpp
@@ -94,4 +94,8 @@
     return INVALID_OPERATION;
 }
 
+std::vector<IServiceManager::ServiceDebugInfo> ServiceManager::getServiceDebugInfo() {
+    std::vector<IServiceManager::ServiceDebugInfo> ret;
+    return ret;
+}
 }  // namespace android
diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h
index 6d6e008..e0af5d4 100644
--- a/libs/fakeservicemanager/ServiceManager.h
+++ b/libs/fakeservicemanager/ServiceManager.h
@@ -20,6 +20,7 @@
 
 #include <map>
 #include <optional>
+#include <vector>
 
 namespace android {
 
@@ -58,6 +59,9 @@
 
     status_t unregisterForNotifications(const String16& name,
                                         const sp<LocalRegistrationCallback>& callback) override;
+
+    std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override;
+
 private:
     std::map<String16, sp<IBinder>> mNameToService;
 };
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 501f8cf..47d801a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1497,6 +1497,13 @@
 
     releaseBufferIfOverwriting(*s);
 
+    if (buffer == nullptr) {
+        s->what &= ~layer_state_t::eBufferChanged;
+        s->bufferData = nullptr;
+        mContainsBuffer = false;
+        return *this;
+    }
+
     std::shared_ptr<BufferData> bufferData = std::make_shared<BufferData>();
     bufferData->buffer = buffer;
     uint64_t frameNumber = sc->resolveFrameNumber(optFrameNumber);
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index 804ce4f..4e966d1 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -76,7 +76,7 @@
             info.inputConfig == inputConfig && info.displayId == displayId &&
             info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop &&
             info.applicationInfo == applicationInfo && info.layoutParamsType == layoutParamsType &&
-            info.layoutParamsFlags == layoutParamsFlags;
+            info.layoutParamsFlags == layoutParamsFlags && info.isClone == isClone;
 }
 
 status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {
@@ -124,7 +124,8 @@
         parcel->write(touchableRegion) ?:
         parcel->writeBool(replaceTouchableRegionWithCrop) ?:
         parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
-        parcel->writeStrongBinder(windowToken);
+        parcel->writeStrongBinder(windowToken) ?:
+        parcel->writeBool(isClone);
     // clang-format on
     return status;
 }
@@ -175,7 +176,8 @@
         parcel->read(touchableRegion) ?:
         parcel->readBool(&replaceTouchableRegionWithCrop) ?:
         parcel->readNullableStrongBinder(&touchableRegionCropHandleSp) ?:
-        parcel->readNullableStrongBinder(&windowToken);
+        parcel->readNullableStrongBinder(&windowToken) ?:
+        parcel->readBool(&isClone);
     // clang-format on
 
     if (status != OK) {
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index a9977b0..b31b37b 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -54,10 +54,11 @@
      */
     void setPowerMode(IBinder display, int mode);
 
-    /* returns display statistics for a given display
+    /**
+     * Returns display statistics for a given display
      * intended to be used by the media framework to properly schedule
      * video frames */
-    DisplayStatInfo getDisplayStats(IBinder display);
+    DisplayStatInfo getDisplayStats(@nullable IBinder display);
 
      /**
      * Get transactional state of given display.
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index 0e1d258..169f7f0 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -236,6 +236,8 @@
 
     void setInputConfig(ftl::Flags<InputConfig> config, bool value);
 
+    bool isClone = false;
+
     void addTouchableRegion(const Rect& region);
 
     bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp
index c51b244..99658cc 100644
--- a/libs/gui/tests/WindowInfo_test.cpp
+++ b/libs/gui/tests/WindowInfo_test.cpp
@@ -71,6 +71,7 @@
     i.applicationInfo.name = "ApplicationFooBar";
     i.applicationInfo.token = new BBinder();
     i.applicationInfo.dispatchingTimeoutMillis = 0x12345678ABCD;
+    i.isClone = true;
 
     Parcel p;
     i.writeToParcel(&p);
@@ -101,6 +102,7 @@
     ASSERT_EQ(i.replaceTouchableRegionWithCrop, i2.replaceTouchableRegionWithCrop);
     ASSERT_EQ(i.touchableRegionCropHandle, i2.touchableRegionCropHandle);
     ASSERT_EQ(i.applicationInfo, i2.applicationInfo);
+    ASSERT_EQ(i.isClone, i2.isClone);
 }
 
 TEST(InputApplicationInfo, Parcelling) {
diff --git a/libs/input/PrintTools.cpp b/libs/input/PrintTools.cpp
index 5d6ae4e..01f6bf5 100644
--- a/libs/input/PrintTools.cpp
+++ b/libs/input/PrintTools.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "PrintTools"
 
 #include <input/PrintTools.h>
+#include <sstream>
 
 namespace android {
 
@@ -24,4 +25,20 @@
     return value ? "true" : "false";
 }
 
+std::string addLinePrefix(std::string str, const std::string& prefix) {
+    std::stringstream ss;
+    bool newLineStarted = true;
+    for (const auto& ch : str) {
+        if (newLineStarted) {
+            ss << prefix;
+            newLineStarted = false;
+        }
+        if (ch == '\n') {
+            newLineStarted = true;
+        }
+        ss << ch;
+    }
+    return ss.str();
+}
+
 } // namespace android
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index a9380c6..d138495 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -243,6 +243,10 @@
     ],
 
     afdo: true,
+
+    header_abi_checker: {
+        diff_flags: ["-allow-adding-removing-weak-symbols"],
+    },
 }
 
 cc_library_headers {
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 3ea0986..8ce2f35 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -367,7 +367,7 @@
 
 // --- InputClassifier ---
 
-InputClassifier::InputClassifier(InputListenerInterface& listener) : mListener(listener) {}
+InputClassifier::InputClassifier(InputListenerInterface& listener) : mQueuedListener(listener) {}
 
 void InputClassifier::onBinderDied(void* cookie) {
     InputClassifier* classifier = static_cast<InputClassifier*>(cookie);
@@ -417,55 +417,67 @@
 
 void InputClassifier::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
     // pass through
-    mListener.notifyConfigurationChanged(args);
+    mQueuedListener.notifyConfigurationChanged(args);
+    mQueuedListener.flush();
 }
 
 void InputClassifier::notifyKey(const NotifyKeyArgs* args) {
     // pass through
-    mListener.notifyKey(args);
+    mQueuedListener.notifyKey(args);
+    mQueuedListener.flush();
 }
 
 void InputClassifier::notifyMotion(const NotifyMotionArgs* args) {
-    std::scoped_lock lock(mLock);
-    // MotionClassifier is only used for touch events, for now
-    const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(*args);
-    if (!sendToMotionClassifier) {
-        mListener.notifyMotion(args);
-        return;
-    }
-
-    NotifyMotionArgs newArgs(*args);
-    newArgs.classification = mMotionClassifier->classify(newArgs);
-    mListener.notifyMotion(&newArgs);
+    { // acquire lock
+        std::scoped_lock lock(mLock);
+        // MotionClassifier is only used for touch events, for now
+        const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(*args);
+        if (!sendToMotionClassifier) {
+            mQueuedListener.notifyMotion(args);
+        } else {
+            NotifyMotionArgs newArgs(*args);
+            newArgs.classification = mMotionClassifier->classify(newArgs);
+            mQueuedListener.notifyMotion(&newArgs);
+        }
+    } // release lock
+    mQueuedListener.flush();
 }
 
 void InputClassifier::notifySensor(const NotifySensorArgs* args) {
     // pass through
-    mListener.notifySensor(args);
+    mQueuedListener.notifySensor(args);
+    mQueuedListener.flush();
 }
 
 void InputClassifier::notifyVibratorState(const NotifyVibratorStateArgs* args) {
     // pass through
-    mListener.notifyVibratorState(args);
+    mQueuedListener.notifyVibratorState(args);
+    mQueuedListener.flush();
 }
 
 void InputClassifier::notifySwitch(const NotifySwitchArgs* args) {
     // pass through
-    mListener.notifySwitch(args);
+    mQueuedListener.notifySwitch(args);
+    mQueuedListener.flush();
 }
 
 void InputClassifier::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
-    std::scoped_lock lock(mLock);
-    if (mMotionClassifier) {
-        mMotionClassifier->reset(*args);
-    }
+    { // acquire lock
+        std::scoped_lock lock(mLock);
+        if (mMotionClassifier) {
+            mMotionClassifier->reset(*args);
+        }
+    } // release lock
+
     // continue to next stage
-    mListener.notifyDeviceReset(args);
+    mQueuedListener.notifyDeviceReset(args);
+    mQueuedListener.flush();
 }
 
 void InputClassifier::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
     // pass through
-    mListener.notifyPointerCaptureChanged(args);
+    mQueuedListener.notifyPointerCaptureChanged(args);
+    mQueuedListener.flush();
 }
 
 void InputClassifier::setMotionClassifierLocked(
@@ -490,6 +502,10 @@
     dump += "\n";
 }
 
+void InputClassifier::monitor() {
+    std::scoped_lock lock(mLock);
+}
+
 InputClassifier::~InputClassifier() {
 }
 
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index e2a0bc2..56cf760 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -96,6 +96,9 @@
      */
     virtual void dump(std::string& dump) = 0;
 
+    /* Called by the heatbeat to ensures that the classifier has not deadlocked. */
+    virtual void monitor() = 0;
+
     InputClassifierInterface() { }
     virtual ~InputClassifierInterface() { }
 };
@@ -247,6 +250,7 @@
     void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
 
     void dump(std::string& dump) override;
+    void monitor() override;
 
     ~InputClassifier();
 
@@ -257,7 +261,7 @@
     // Protect access to mMotionClassifier, since it may become null via a hidl callback
     std::mutex mLock;
     // The next stage to pass input events to
-    InputListenerInterface& mListener;
+    QueuedInputListener mQueuedListener;
 
     std::unique_ptr<MotionClassifierInterface> mMotionClassifier GUARDED_BY(mLock);
     std::future<void> mInitializeMotionClassifier GUARDED_BY(mLock);
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 7b03631..9767cd9 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -62,8 +62,8 @@
         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
     mDispatcher = createInputDispatcher(dispatcherPolicy);
     mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
-    mUnwantedInteractionBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
-    mReader = createInputReader(readerPolicy, *mUnwantedInteractionBlocker);
+    mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
+    mReader = createInputReader(readerPolicy, *mBlocker);
 }
 
 InputManager::~InputManager() {
@@ -111,7 +111,7 @@
 }
 
 UnwantedInteractionBlockerInterface& InputManager::getUnwantedInteractionBlocker() {
-    return *mUnwantedInteractionBlocker;
+    return *mBlocker;
 }
 
 InputClassifierInterface& InputManager::getClassifier() {
@@ -122,6 +122,13 @@
     return *mDispatcher;
 }
 
+void InputManager::monitor() {
+    mReader->monitor();
+    mBlocker->monitor();
+    mClassifier->monitor();
+    mDispatcher->monitor();
+}
+
 // Used by tests only.
 binder::Status InputManager::createInputChannel(const std::string& name, InputChannel* outChannel) {
     IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 35d2b0f..8aad35b 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -90,6 +90,9 @@
 
     /* Gets the input dispatcher. */
     virtual InputDispatcherInterface& getDispatcher() = 0;
+
+    /* Check that the input stages have not deadlocked. */
+    virtual void monitor() = 0;
 };
 
 class InputManager : public InputManagerInterface, public BnInputFlinger {
@@ -108,6 +111,7 @@
     UnwantedInteractionBlockerInterface& getUnwantedInteractionBlocker() override;
     InputClassifierInterface& getClassifier() override;
     InputDispatcherInterface& getDispatcher() override;
+    void monitor() override;
 
     status_t dump(int fd, const Vector<String16>& args) override;
     binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;
@@ -117,7 +121,7 @@
 private:
     std::unique_ptr<InputReaderInterface> mReader;
 
-    std::unique_ptr<UnwantedInteractionBlockerInterface> mUnwantedInteractionBlocker;
+    std::unique_ptr<UnwantedInteractionBlockerInterface> mBlocker;
 
     std::unique_ptr<InputClassifierInterface> mClassifier;
 
diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp
index b69e16a..f57ff33 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.cpp
+++ b/services/inputflinger/UnwantedInteractionBlocker.cpp
@@ -18,6 +18,7 @@
 #include "UnwantedInteractionBlocker.h"
 
 #include <android-base/stringprintf.h>
+#include <input/PrintTools.h>
 #include <inttypes.h>
 #include <linux/input-event-codes.h>
 #include <linux/input.h>
@@ -80,47 +81,6 @@
     return MT_TOOL_FINGER;
 }
 
-static std::string addPrefix(std::string str, const std::string& prefix) {
-    std::stringstream ss;
-    bool newLineStarted = true;
-    for (const auto& ch : str) {
-        if (newLineStarted) {
-            ss << prefix;
-            newLineStarted = false;
-        }
-        if (ch == '\n') {
-            newLineStarted = true;
-        }
-        ss << ch;
-    }
-    return ss.str();
-}
-
-template <typename T>
-static std::string dumpSet(const std::set<T>& v) {
-    static_assert(std::is_integral<T>::value, "Only integral types can be printed.");
-    std::string out;
-    for (const T& entry : v) {
-        out += out.empty() ? "{" : ", ";
-        out += android::base::StringPrintf("%i", entry);
-    }
-    return out.empty() ? "{}" : (out + "}");
-}
-
-template <typename K, typename V>
-static std::string dumpMap(const std::map<K, V>& map) {
-    static_assert(std::is_integral<K>::value, "Keys should have integral type to be printed.");
-    static_assert(std::is_integral<V>::value, "Values should have integral type to be printed.");
-    std::string out;
-    for (const auto& [k, v] : map) {
-        if (!out.empty()) {
-            out += "\n";
-        }
-        out += android::base::StringPrintf("%i : %i", static_cast<int>(k), static_cast<int>(v));
-    }
-    return out;
-}
-
 static std::string dumpDeviceInfo(const AndroidPalmFilterDeviceInfo& info) {
     std::string out;
     out += StringPrintf("max_x = %.2f\n", info.max_x);
@@ -168,10 +128,6 @@
     return AMOTION_EVENT_ACTION_MOVE;
 }
 
-static const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
 std::string toString(const ::ui::InProgressTouchEvdev& touch) {
     return StringPrintf("x=%.1f, y=%.1f, tracking_id=%i, slot=%zu,"
                         " pressure=%.1f, major=%i, minor=%i, "
@@ -356,69 +312,87 @@
 
 UnwantedInteractionBlocker::UnwantedInteractionBlocker(InputListenerInterface& listener,
                                                        bool enablePalmRejection)
-      : mListener(listener), mEnablePalmRejection(enablePalmRejection) {}
+      : mQueuedListener(listener), mEnablePalmRejection(enablePalmRejection) {}
 
 void UnwantedInteractionBlocker::notifyConfigurationChanged(
         const NotifyConfigurationChangedArgs* args) {
-    mListener.notifyConfigurationChanged(args);
+    mQueuedListener.notifyConfigurationChanged(args);
+    mQueuedListener.flush();
 }
 
 void UnwantedInteractionBlocker::notifyKey(const NotifyKeyArgs* args) {
-    mListener.notifyKey(args);
+    mQueuedListener.notifyKey(args);
+    mQueuedListener.flush();
 }
 
 void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs* args) {
-    const std::vector<NotifyMotionArgs> processedArgs =
-            mPreferStylusOverTouchBlocker.processMotion(*args);
-    for (const NotifyMotionArgs& loopArgs : processedArgs) {
-        notifyMotionInner(&loopArgs);
-    }
+    { // acquire lock
+        std::scoped_lock lock(mLock);
+        const std::vector<NotifyMotionArgs> processedArgs =
+                mPreferStylusOverTouchBlocker.processMotion(*args);
+        for (const NotifyMotionArgs& loopArgs : processedArgs) {
+            notifyMotionLocked(&loopArgs);
+        }
+    } // release lock
+
+    // Call out to the next stage without holding the lock
+    mQueuedListener.flush();
 }
 
-void UnwantedInteractionBlocker::notifyMotionInner(const NotifyMotionArgs* args) {
+void UnwantedInteractionBlocker::notifyMotionLocked(const NotifyMotionArgs* args) {
     auto it = mPalmRejectors.find(args->deviceId);
     const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args->source);
     if (!sendToPalmRejector) {
-        mListener.notifyMotion(args);
+        mQueuedListener.notifyMotion(args);
         return;
     }
 
-    const std::vector<NotifyMotionArgs> newMotions = it->second.processMotion(*args);
-    for (const NotifyMotionArgs& newArgs : newMotions) {
-        mListener.notifyMotion(&newArgs);
+    std::vector<NotifyMotionArgs> processedArgs = it->second.processMotion(*args);
+    for (const NotifyMotionArgs& loopArgs : processedArgs) {
+        mQueuedListener.notifyMotion(&loopArgs);
     }
 }
 
 void UnwantedInteractionBlocker::notifySwitch(const NotifySwitchArgs* args) {
-    mListener.notifySwitch(args);
+    mQueuedListener.notifySwitch(args);
+    mQueuedListener.flush();
 }
 
 void UnwantedInteractionBlocker::notifySensor(const NotifySensorArgs* args) {
-    mListener.notifySensor(args);
+    mQueuedListener.notifySensor(args);
+    mQueuedListener.flush();
 }
 
 void UnwantedInteractionBlocker::notifyVibratorState(const NotifyVibratorStateArgs* args) {
-    mListener.notifyVibratorState(args);
+    mQueuedListener.notifyVibratorState(args);
+    mQueuedListener.flush();
 }
 void UnwantedInteractionBlocker::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
-    auto it = mPalmRejectors.find(args->deviceId);
-    if (it != mPalmRejectors.end()) {
-        AndroidPalmFilterDeviceInfo info = it->second.getPalmFilterDeviceInfo();
-        // Re-create the object instead of resetting it
-        mPalmRejectors.erase(it);
-        mPalmRejectors.emplace(args->deviceId, info);
-    }
-    mListener.notifyDeviceReset(args);
-    mPreferStylusOverTouchBlocker.notifyDeviceReset(*args);
+    { // acquire lock
+        std::scoped_lock lock(mLock);
+        auto it = mPalmRejectors.find(args->deviceId);
+        if (it != mPalmRejectors.end()) {
+            AndroidPalmFilterDeviceInfo info = it->second.getPalmFilterDeviceInfo();
+            // Re-create the object instead of resetting it
+            mPalmRejectors.erase(it);
+            mPalmRejectors.emplace(args->deviceId, info);
+        }
+        mQueuedListener.notifyDeviceReset(args);
+        mPreferStylusOverTouchBlocker.notifyDeviceReset(*args);
+    } // release lock
+    // Send events to the next stage without holding the lock
+    mQueuedListener.flush();
 }
 
 void UnwantedInteractionBlocker::notifyPointerCaptureChanged(
         const NotifyPointerCaptureChangedArgs* args) {
-    mListener.notifyPointerCaptureChanged(args);
+    mQueuedListener.notifyPointerCaptureChanged(args);
+    mQueuedListener.flush();
 }
 
 void UnwantedInteractionBlocker::notifyInputDevicesChanged(
         const std::vector<InputDeviceInfo>& inputDevices) {
+    std::scoped_lock lock(mLock);
     if (!mEnablePalmRejection) {
         // Palm rejection is disabled. Don't create any palm rejector objects.
         return;
@@ -450,20 +424,23 @@
 }
 
 void UnwantedInteractionBlocker::dump(std::string& dump) {
+    std::scoped_lock lock(mLock);
     dump += "UnwantedInteractionBlocker:\n";
     dump += "  mPreferStylusOverTouchBlocker:\n";
-    dump += addPrefix(mPreferStylusOverTouchBlocker.dump(), "    ");
+    dump += addLinePrefix(mPreferStylusOverTouchBlocker.dump(), "    ");
     dump += StringPrintf("  mEnablePalmRejection: %s\n", toString(mEnablePalmRejection));
     dump += StringPrintf("  isPalmRejectionEnabled (flag value): %s\n",
                          toString(isPalmRejectionEnabled()));
     dump += mPalmRejectors.empty() ? "  mPalmRejectors: None\n" : "  mPalmRejectors:\n";
     for (const auto& [deviceId, palmRejector] : mPalmRejectors) {
         dump += StringPrintf("    deviceId = %" PRId32 ":\n", deviceId);
-        dump += addPrefix(palmRejector.dump(), "      ");
+        dump += addLinePrefix(palmRejector.dump(), "      ");
     }
 }
 
-void UnwantedInteractionBlocker::monitor() {}
+void UnwantedInteractionBlocker::monitor() {
+    std::scoped_lock lock(mLock);
+}
 
 UnwantedInteractionBlocker::~UnwantedInteractionBlocker() {}
 
@@ -529,9 +506,9 @@
 
 std::string SlotState::dump() const {
     std::string out = "mSlotsByPointerId:\n";
-    out += addPrefix(dumpMap(mSlotsByPointerId), "  ") + "\n";
+    out += addLinePrefix(dumpMap(mSlotsByPointerId), "  ") + "\n";
     out += "mPointerIdsBySlot:\n";
-    out += addPrefix(dumpMap(mPointerIdsBySlot), "  ") + "\n";
+    out += addLinePrefix(dumpMap(mPointerIdsBySlot), "  ") + "\n";
     return out;
 }
 
@@ -689,9 +666,9 @@
 std::string PalmRejector::dump() const {
     std::string out;
     out += "mDeviceInfo:\n";
-    out += addPrefix(dumpDeviceInfo(mDeviceInfo), "  ");
+    out += addLinePrefix(dumpDeviceInfo(mDeviceInfo), "  ");
     out += "mSlotState:\n";
-    out += addPrefix(mSlotState.dump(), "  ");
+    out += addLinePrefix(mSlotState.dump(), "  ");
     out += "mSuppressedPointerIds: ";
     out += dumpSet(mSuppressedPointerIds) + "\n";
     return out;
diff --git a/services/inputflinger/UnwantedInteractionBlocker.h b/services/inputflinger/UnwantedInteractionBlocker.h
index 8a1cd72..a433764 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.h
+++ b/services/inputflinger/UnwantedInteractionBlocker.h
@@ -19,6 +19,7 @@
 #include <map>
 #include <set>
 
+#include <android-base/thread_annotations.h>
 #include "include/UnwantedInteractionBlockerInterface.h"
 #include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h"
 #include "ui/events/ozone/evdev/touch_filter/palm_detection_filter.h"
@@ -86,18 +87,20 @@
     ~UnwantedInteractionBlocker();
 
 private:
+    std::mutex mLock;
     // The next stage to pass input events to
-    InputListenerInterface& mListener;
+
+    QueuedInputListener mQueuedListener;
     const bool mEnablePalmRejection;
 
     // When stylus is down, ignore touch
-    PreferStylusOverTouchBlocker mPreferStylusOverTouchBlocker;
+    PreferStylusOverTouchBlocker mPreferStylusOverTouchBlocker GUARDED_BY(mLock);
 
     // Detect and reject unwanted palms on screen
     // Use a separate palm rejector for every touch device.
-    std::map<int32_t /*deviceId*/, PalmRejector> mPalmRejectors;
+    std::map<int32_t /*deviceId*/, PalmRejector> mPalmRejectors GUARDED_BY(mLock);
     // TODO(b/210159205): delete this when simultaneous stylus and touch is supported
-    void notifyMotionInner(const NotifyMotionArgs* args);
+    void notifyMotionLocked(const NotifyMotionArgs* args) REQUIRES(mLock);
 };
 
 class SlotState {
diff --git a/services/inputflinger/include/UnwantedInteractionBlockerInterface.h b/services/inputflinger/include/UnwantedInteractionBlockerInterface.h
index 2327266..1a6f847 100644
--- a/services/inputflinger/include/UnwantedInteractionBlockerInterface.h
+++ b/services/inputflinger/include/UnwantedInteractionBlockerInterface.h
@@ -39,11 +39,11 @@
 
     /**
      * Dump the state of the interaction blocker.
-     * This method may be called on any thread (usually by the input manager).
+     * This method may be called on any thread (usually by the input manager on a binder thread).
      */
     virtual void dump(std::string& dump) = 0;
 
-    /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */
+    /* Called by the heatbeat to ensures that the blocker has not deadlocked. */
     virtual void monitor() = 0;
 
     UnwantedInteractionBlockerInterface() {}
diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
index e378096..0062f42 100644
--- a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
+++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
@@ -19,6 +19,7 @@
 #include <gtest/gtest.h>
 #include <gui/constants.h>
 #include <linux/input.h>
+#include <thread>
 
 #include "TestInputListener.h"
 
@@ -547,6 +548,27 @@
     mBlocker->notifyMotion(&args);
 }
 
+/**
+ * Call dump, and on another thread, try to send some motions. The blocker should
+ * not crash. On 2022 hardware, this test requires ~ 13K executions (about 20 seconds) to reproduce
+ * the original bug. This is meant to be run with "--gtest_repeat=100000 --gtest_break_on_failure"
+ * options
+ */
+TEST_F(UnwantedInteractionBlockerTest, DumpCanBeAccessedOnAnotherThread) {
+    mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+    NotifyMotionArgs args1 = generateMotionArgs(0 /*downTime*/, 0 /*eventTime*/, DOWN, {{1, 2, 3}});
+    mBlocker->notifyMotion(&args1);
+    std::thread dumpThread([this]() {
+        std::string dump;
+        mBlocker->dump(dump);
+    });
+    NotifyMotionArgs args2 = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, MOVE, {{4, 5, 6}});
+    mBlocker->notifyMotion(&args2);
+    NotifyMotionArgs args3 = generateMotionArgs(0 /*downTime*/, 2 /*eventTime*/, UP, {{4, 5, 6}});
+    mBlocker->notifyMotion(&args3);
+    dumpThread.join();
+}
+
 using UnwantedInteractionBlockerTestDeathTest = UnwantedInteractionBlockerTest;
 
 /**
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 5ffbb7f..742af58 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -416,7 +416,12 @@
 
     if (outputDependentState.overrideInfo.buffer != nullptr) {
         displayFrame = outputDependentState.overrideInfo.displayFrame;
-        sourceCrop = displayFrame.toFloatRect();
+        sourceCrop =
+                FloatRect(0.f, 0.f,
+                          static_cast<float>(outputDependentState.overrideInfo.buffer->getBuffer()
+                                                     ->getWidth()),
+                          static_cast<float>(outputDependentState.overrideInfo.buffer->getBuffer()
+                                                     ->getHeight()));
     }
 
     ALOGV("Writing display frame [%d, %d, %d, %d]", displayFrame.left, displayFrame.top,
@@ -790,7 +795,7 @@
     // framebuffer space of the override buffer to layer space.
     const ProjectionSpace& layerSpace = getOutput().getState().layerStackSpace;
     const ui::Transform transform = getState().overrideInfo.displaySpace.getTransform(layerSpace);
-    const Rect boundaries = transform.transform(getState().overrideInfo.displaySpace.getContent());
+    const Rect boundaries = transform.transform(getState().overrideInfo.displayFrame);
 
     LayerFE::LayerSettings settings;
     settings.geometry = renderengine::Geometry{
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index 0918510..250f648 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -316,7 +316,7 @@
                         state.overrideInfo = {
                                 .buffer = mNewCachedSet->getBuffer(),
                                 .acquireFence = mNewCachedSet->getDrawFence(),
-                                .displayFrame = mNewCachedSet->getBounds(),
+                                .displayFrame = mNewCachedSet->getTextureBounds(),
                                 .dataspace = mNewCachedSet->getOutputDataspace(),
                                 .displaySpace = mNewCachedSet->getOutputSpace(),
                                 .damageRegion = Region::INVALID_REGION,
@@ -356,7 +356,7 @@
                 state.overrideInfo = {
                         .buffer = currentLayerIter->getBuffer(),
                         .acquireFence = currentLayerIter->getDrawFence(),
-                        .displayFrame = currentLayerIter->getBounds(),
+                        .displayFrame = currentLayerIter->getTextureBounds(),
                         .dataspace = currentLayerIter->getOutputDataspace(),
                         .displaySpace = currentLayerIter->getOutputSpace(),
                         .damageRegion = Region(),
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 7038e8c..5290bd9 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -940,7 +940,7 @@
                                                    84.f / 255.f};
 const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044};
 const Rect OutputLayerWriteStateToHWCTest::kOverrideDisplayFrame{1002, 1003, 1004, 20044};
-const FloatRect OutputLayerWriteStateToHWCTest::kOverrideSourceCrop{1002, 1003, 1004, 20044};
+const FloatRect OutputLayerWriteStateToHWCTest::kOverrideSourceCrop{0.f, 0.f, 4.f, 5.f};
 const Region OutputLayerWriteStateToHWCTest::kOutputSpaceVisibleRegion{
         Rect{1005, 1006, 1007, 1008}};
 const Region OutputLayerWriteStateToHWCTest::kOverrideVisibleRegion{Rect{1006, 1007, 1008, 1009}};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b1de966..6ed4a94 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2391,6 +2391,7 @@
     // If the layer is a clone, we need to crop the input region to cloned root to prevent
     // touches from going outside the cloned area.
     if (isClone()) {
+        info.isClone = true;
         if (const sp<Layer> clonedRoot = getClonedRoot()) {
             const Rect rect = displayTransform.transform(Rect{clonedRoot->mScreenBounds});
             info.touchableRegion = info.touchableRegion.intersect(rect);
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index 027a15e..a6d7f58 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -465,4 +465,22 @@
     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
 }
 
+TEST_F(ReleaseBufferCallbackTest, SetBuffer_OverwriteBuffersWithNull) {
+    sp<SurfaceControl> layer = createBufferStateLayer();
+    ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
+
+    sp<GraphicBuffer> firstBuffer = getBuffer();
+    ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
+
+    // Create transaction with a buffer.
+    Transaction transaction;
+    transaction.setBuffer(layer, firstBuffer, std::nullopt, firstBufferCallbackId.framenumber,
+                          releaseCallback->getCallback());
+
+    // Call setBuffer on the same transaction with a null buffer.
+    transaction.setBuffer(layer, nullptr, std::nullopt, 0, releaseCallback->getCallback());
+
+    ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
+}
+
 } // namespace android