diff --git a/include/input/Input.h b/include/input/Input.h
index 55ebb90..e421dee 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -534,7 +534,7 @@
 
     inline int32_t getActionMasked() const { return getActionMasked(mAction); }
 
-    static int32_t getActionIndex(int32_t action) {
+    static uint8_t getActionIndex(int32_t action) {
         return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
                 AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
     }
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index ec58325..22a69e5 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -49,6 +49,7 @@
     srcs: [
         "InputClassifier.cpp",
         "InputClassifierConverter.cpp",
+        "UnwantedInteractionBlocker.cpp",
         "InputManager.cpp",
     ],
 }
@@ -60,6 +61,7 @@
         "android.hardware.input.classifier@1.0",
         "libbase",
         "libbinder",
+        "libchrome",
         "libcrypto",
         "libcutils",
         "libhidlbase",
@@ -76,6 +78,7 @@
     ],
     static_libs: [
         "libattestation",
+        "libpalmrejection",
     ],
 }
 
diff --git a/services/inputflinger/InputClassifierConverter.cpp b/services/inputflinger/InputClassifierConverter.cpp
index fc8c7c3..b58a188 100644
--- a/services/inputflinger/InputClassifierConverter.cpp
+++ b/services/inputflinger/InputClassifierConverter.cpp
@@ -325,11 +325,6 @@
     return out;
 }
 
-static uint8_t getActionIndex(int32_t action) {
-    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
-            AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-}
-
 static void getHidlPropertiesAndCoords(const NotifyMotionArgs& args,
         std::vector<common::V1_0::PointerProperties>* outPointerProperties,
         std::vector<common::V1_0::PointerCoords>* outPointerCoords) {
@@ -360,7 +355,7 @@
     event.eventTime = args.eventTime;
     event.deviceTimestamp = 0;
     event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK);
-    event.actionIndex = getActionIndex(args.action);
+    event.actionIndex = MotionEvent::getActionIndex(args.action);
     event.actionButton = getActionButton(args.actionButton);
     event.flags = getFlags(args.flags);
     event.policyFlags = getPolicyFlags(args.policyFlags);
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 158d0eb..73b63e3 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -188,6 +188,25 @@
     return true;
 }
 
+std::string NotifyMotionArgs::dump() const {
+    std::string coords;
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        if (!coords.empty()) {
+            coords += ", ";
+        }
+        coords += StringPrintf("{%" PRIu32 ": ", i);
+        coords +=
+                StringPrintf("id=%" PRIu32 " x=%.1f y=%.1f, pressure=%.1f", pointerProperties[i].id,
+                             pointerCoords[i].getX(), pointerCoords[i].getY(),
+                             pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+        coords += "}";
+    }
+    return StringPrintf("NotifyMotionArgs(id=%" PRId32 ", eventTime=%" PRId64 ", deviceId=%" PRId32
+                        ", source=%s, action=%s, pointerCount=%" PRIu32 " pointers=%s)",
+                        id, eventTime, deviceId, inputEventSourceToString(source).c_str(),
+                        MotionEvent::actionToString(action).c_str(), pointerCount, coords.c_str());
+}
+
 void NotifyMotionArgs::notify(InputListenerInterface& listener) const {
     listener.notifyMotion(this);
 }
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 221e193..7a9862d 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -21,6 +21,7 @@
 #include "InputManager.h"
 #include "InputDispatcherFactory.h"
 #include "InputReaderFactory.h"
+#include "UnwantedInteractionBlocker.h"
 
 #include <binder/IPCThreadState.h>
 
@@ -54,12 +55,17 @@
     }
 }
 
+/**
+ * The event flow is via the "InputListener" interface, as follows:
+ * InputReader -> UnwantedInteractionBlocker -> InputClassifier -> InputDispatcher
+ */
 InputManager::InputManager(
         const sp<InputReaderPolicyInterface>& readerPolicy,
         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
     mDispatcher = createInputDispatcher(dispatcherPolicy);
     mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
-    mReader = createInputReader(readerPolicy, *mClassifier);
+    mUnwantedInteractionBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
+    mReader = createInputReader(readerPolicy, *mUnwantedInteractionBlocker);
 }
 
 InputManager::~InputManager() {
@@ -106,6 +112,10 @@
     return *mReader;
 }
 
+UnwantedInteractionBlockerInterface& InputManager::getUnwantedInteractionBlocker() {
+    return *mUnwantedInteractionBlocker;
+}
+
 InputClassifierInterface& InputManager::getClassifier() {
     return *mClassifier;
 }
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index e000283..35d2b0f 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -23,6 +23,7 @@
 
 #include "InputClassifier.h"
 #include "InputReaderBase.h"
+#include "include/UnwantedInteractionBlockerInterface.h"
 
 #include <InputDispatcherInterface.h>
 #include <InputDispatcherPolicyInterface.h>
@@ -46,11 +47,16 @@
  * The input manager has three components.
  *
  * 1. The InputReader class starts a thread that reads and preprocesses raw input events, applies
- *    policy, and posts messages to a queue managed by the InputClassifier.
- * 2. The InputClassifier class starts a thread to communicate with the device-specific
- *    classifiers. It then waits on the queue of events from InputReader, applies a classification
- *    to them, and queues them for the InputDispatcher.
- * 3. The InputDispatcher class starts a thread that waits for new events on the
+ *    policy, and posts messages to a queue managed by the UnwantedInteractionBlocker.
+ * 2. The UnwantedInteractionBlocker is responsible for removing unwanted interactions. For example,
+ *    this could be a palm on the screen. This stage would alter the event stream to remove either
+ *    partially (some of the pointers) or fully (all touches) the unwanted interaction. The events
+ *    are processed on the InputReader thread, without any additional queue. The events are then
+ *    posted to the queue managed by the InputClassifier.
+ * 3. The InputClassifier class starts a thread to communicate with the device-specific
+ *    classifiers. It then waits on the queue of events from UnwantedInteractionBlocker, applies
+ *    a classification to them, and queues them for the InputDispatcher.
+ * 4. The InputDispatcher class starts a thread that waits for new events on the
  *    previous queue and asynchronously dispatches them to applications.
  *
  * By design, none of these classes share any internal state.  Moreover, all communication is
@@ -76,6 +82,9 @@
     /* Gets the input reader. */
     virtual InputReaderInterface& getReader() = 0;
 
+    /* Gets the unwanted interaction blocker. */
+    virtual UnwantedInteractionBlockerInterface& getUnwantedInteractionBlocker() = 0;
+
     /* Gets the input classifier */
     virtual InputClassifierInterface& getClassifier() = 0;
 
@@ -96,6 +105,7 @@
     status_t stop() override;
 
     InputReaderInterface& getReader() override;
+    UnwantedInteractionBlockerInterface& getUnwantedInteractionBlocker() override;
     InputClassifierInterface& getClassifier() override;
     InputDispatcherInterface& getDispatcher() override;
 
@@ -107,6 +117,8 @@
 private:
     std::unique_ptr<InputReaderInterface> mReader;
 
+    std::unique_ptr<UnwantedInteractionBlockerInterface> mUnwantedInteractionBlocker;
+
     std::unique_ptr<InputClassifierInterface> mClassifier;
 
     std::unique_ptr<InputDispatcherInterface> mDispatcher;
diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp
new file mode 100644
index 0000000..64dbb8c
--- /dev/null
+++ b/services/inputflinger/UnwantedInteractionBlocker.cpp
@@ -0,0 +1,687 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "UnwantedInteractionBlocker"
+#include "UnwantedInteractionBlocker.h"
+
+#include <android-base/stringprintf.h>
+#include <inttypes.h>
+#include <linux/input-event-codes.h>
+#include <linux/input.h>
+#include <server_configurable_flags/get_flags.h>
+
+#include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h"
+#include "ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.h"
+
+using android::base::StringPrintf;
+
+namespace android {
+
+// Category (=namespace) name for the input settings that are applied at boot time
+static const char* INPUT_NATIVE_BOOT = "input_native_boot";
+/**
+ * Feature flag name. This flag determines whether palm rejection is enabled. To enable, specify
+ * 'true' (not case sensitive) or '1'. To disable, specify any other value.
+ */
+static const char* PALM_REJECTION_ENABLED = "palm_rejection_enabled";
+
+static std::string toLower(std::string s) {
+    std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
+    return s;
+}
+
+static bool isFromTouchscreen(int32_t source) {
+    return isFromSource(source, AINPUT_SOURCE_TOUCHSCREEN);
+}
+
+static ::base::TimeTicks toChromeTimestamp(nsecs_t eventTime) {
+    return ::base::TimeTicks::UnixEpoch() +
+            ::base::Milliseconds(static_cast<float>(ns2ms(eventTime)));
+}
+
+/**
+ * Return true if palm rejection is enabled via the server configurable flags. Return false
+ * otherwise.
+ */
+static bool isPalmRejectionEnabled() {
+    std::string value = toLower(
+            server_configurable_flags::GetServerConfigurableFlag(INPUT_NATIVE_BOOT,
+                                                                 PALM_REJECTION_ENABLED, "false"));
+    if (value == "true" || value == "1") {
+        return true;
+    }
+    return false;
+}
+
+static int getLinuxToolType(int32_t toolType) {
+    switch (toolType) {
+        case AMOTION_EVENT_TOOL_TYPE_FINGER:
+            return MT_TOOL_FINGER;
+        case AMOTION_EVENT_TOOL_TYPE_STYLUS:
+            return MT_TOOL_PEN;
+        case AMOTION_EVENT_TOOL_TYPE_PALM:
+            return MT_TOOL_PALM;
+    }
+    ALOGW("Got tool type %" PRId32 ", converting to MT_TOOL_FINGER", toolType);
+    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);
+    out += StringPrintf("max_y = %.2f\n", info.max_y);
+    out += StringPrintf("x_res = %.2f\n", info.x_res);
+    out += StringPrintf("y_res = %.2f\n", info.y_res);
+    out += StringPrintf("major_radius_res = %.2f\n", info.major_radius_res);
+    out += StringPrintf("minor_radius_res = %.2f\n", info.minor_radius_res);
+    out += StringPrintf("minor_radius_supported = %s\n",
+                        info.minor_radius_supported ? "true" : "false");
+    out += StringPrintf("touch_major_res = %" PRId32 "\n", info.touch_major_res);
+    out += StringPrintf("touch_minor_res = %" PRId32 "\n", info.touch_minor_res);
+    return out;
+}
+
+static int32_t getActionUpForPointerId(const NotifyMotionArgs& args, int32_t pointerId) {
+    for (size_t i = 0; i < args.pointerCount; i++) {
+        if (pointerId == args.pointerProperties[i].id) {
+            return AMOTION_EVENT_ACTION_POINTER_UP |
+                    (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+        }
+    }
+    LOG_ALWAYS_FATAL("Can't find pointerId %" PRId32 " in %s", pointerId, args.dump().c_str());
+}
+
+/**
+ * Find the action for individual pointer at the given pointer index.
+ * This is always equal to MotionEvent::getActionMasked, except for
+ * POINTER_UP or POINTER_DOWN events. For example, in a POINTER_UP event, the action for
+ * the active pointer is ACTION_POINTER_UP, while the action for the other pointers is ACTION_MOVE.
+ */
+static int32_t resolveActionForPointer(uint8_t pointerIndex, int32_t action) {
+    const int32_t actionMasked = MotionEvent::getActionMasked(action);
+    if (actionMasked != AMOTION_EVENT_ACTION_POINTER_DOWN &&
+        actionMasked != AMOTION_EVENT_ACTION_POINTER_UP) {
+        return actionMasked;
+    }
+    // This is a POINTER_DOWN or POINTER_UP event
+    const uint8_t actionIndex = MotionEvent::getActionIndex(action);
+    if (pointerIndex == actionIndex) {
+        return actionMasked;
+    }
+    // When POINTER_DOWN or POINTER_UP happens, it's actually a MOVE for all of the other
+    // pointers
+    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, "
+                        "tool_type=%i, altered=%s, was_touching=%s, touching=%s",
+                        touch.x, touch.y, touch.tracking_id, touch.slot, touch.pressure,
+                        touch.major, touch.minor, touch.tool_type, toString(touch.altered),
+                        toString(touch.was_touching), toString(touch.touching));
+}
+
+/**
+ * Remove the data for the provided pointers from the args. The pointers are identified by their
+ * pointerId, not by the index inside the array.
+ * Return the new NotifyMotionArgs struct that has the remaining pointers.
+ * The only fields that may be different in the returned args from the provided args are:
+ *     - action
+ *     - pointerCount
+ *     - pointerProperties
+ *     - pointerCoords
+ * Action might change because it contains a pointer index. If another pointer is removed, the
+ * active pointer index would be shifted.
+ * Do not call this function for events with POINTER_UP or POINTER_DOWN events when removed pointer
+ * id is the acting pointer id.
+ *
+ * @param args the args from which the pointers should be removed
+ * @param pointerIds the pointer ids of the pointers that should be removed
+ */
+NotifyMotionArgs removePointerIds(const NotifyMotionArgs& args,
+                                  const std::set<int32_t>& pointerIds) {
+    const uint8_t actionIndex = MotionEvent::getActionIndex(args.action);
+    const int32_t actionMasked = MotionEvent::getActionMasked(args.action);
+    const bool isPointerUpOrDownAction = actionMasked == AMOTION_EVENT_ACTION_POINTER_DOWN ||
+            actionMasked == AMOTION_EVENT_ACTION_POINTER_UP;
+
+    NotifyMotionArgs newArgs{args};
+    newArgs.pointerCount = 0;
+    int32_t newActionIndex = 0;
+    for (uint32_t i = 0; i < args.pointerCount; i++) {
+        const int32_t pointerId = args.pointerProperties[i].id;
+        if (pointerIds.find(pointerId) != pointerIds.end()) {
+            // skip this pointer
+            if (isPointerUpOrDownAction && i == actionIndex) {
+                // The active pointer is being removed, so the action is no longer valid.
+                // Set the action to 'UNKNOWN' here. The caller is responsible for updating this
+                // action later to a proper value.
+                newArgs.action = ACTION_UNKNOWN;
+            }
+            continue;
+        }
+        newArgs.pointerProperties[newArgs.pointerCount].copyFrom(args.pointerProperties[i]);
+        newArgs.pointerCoords[newArgs.pointerCount].copyFrom(args.pointerCoords[i]);
+        if (i == actionIndex) {
+            newActionIndex = newArgs.pointerCount;
+        }
+        newArgs.pointerCount++;
+    }
+    // Update POINTER_DOWN or POINTER_UP actions
+    if (isPointerUpOrDownAction && newArgs.action != ACTION_UNKNOWN) {
+        newArgs.action =
+                actionMasked | (newActionIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+        // Convert POINTER_DOWN and POINTER_UP to DOWN and UP if there's only 1 pointer remaining
+        if (newArgs.pointerCount == 1) {
+            if (actionMasked == AMOTION_EVENT_ACTION_POINTER_DOWN) {
+                newArgs.action = AMOTION_EVENT_ACTION_DOWN;
+            } else if (actionMasked == AMOTION_EVENT_ACTION_POINTER_UP) {
+                newArgs.action = AMOTION_EVENT_ACTION_UP;
+            }
+        }
+    }
+    return newArgs;
+}
+
+std::optional<AndroidPalmFilterDeviceInfo> createPalmFilterDeviceInfo(
+        const InputDeviceInfo& deviceInfo) {
+    if (!isFromTouchscreen(deviceInfo.getSources())) {
+        return std::nullopt;
+    }
+    AndroidPalmFilterDeviceInfo out;
+    const InputDeviceInfo::MotionRange* axisX =
+            deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
+    if (axisX != nullptr) {
+        out.max_x = axisX->max;
+        out.x_res = axisX->resolution;
+    } else {
+        ALOGW("Palm rejection is disabled for %s because AXIS_X is not supported",
+              deviceInfo.getDisplayName().c_str());
+        return std::nullopt;
+    }
+    const InputDeviceInfo::MotionRange* axisY =
+            deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
+    if (axisY != nullptr) {
+        out.max_y = axisY->max;
+        out.y_res = axisY->resolution;
+    } else {
+        ALOGW("Palm rejection is disabled for %s because AXIS_Y is not supported",
+              deviceInfo.getDisplayName().c_str());
+        return std::nullopt;
+    }
+    const InputDeviceInfo::MotionRange* axisMajor =
+            deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR, AINPUT_SOURCE_TOUCHSCREEN);
+    if (axisMajor != nullptr) {
+        out.major_radius_res = axisMajor->resolution;
+        out.touch_major_res = axisMajor->resolution;
+    } else {
+        return std::nullopt;
+    }
+    const InputDeviceInfo::MotionRange* axisMinor =
+            deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR, AINPUT_SOURCE_TOUCHSCREEN);
+    if (axisMinor != nullptr) {
+        out.minor_radius_res = axisMinor->resolution;
+        out.touch_minor_res = axisMinor->resolution;
+        out.minor_radius_supported = true;
+    } else {
+        out.minor_radius_supported = false;
+    }
+
+    return out;
+}
+
+/**
+ * Synthesize CANCEL events for any new pointers that should be canceled, while removing pointers
+ * that have already been canceled.
+ * The flow of the function is as follows:
+ * 1. Remove all already canceled pointers
+ * 2. Cancel all newly suppressed pointers
+ * 3. Decide what to do with the current event : keep it, or drop it
+ * The pointers can never be "unsuppressed": once a pointer is canceled, it will never become valid.
+ */
+std::vector<NotifyMotionArgs> cancelSuppressedPointers(
+        const NotifyMotionArgs& args, const std::set<int32_t>& oldSuppressedPointerIds,
+        const std::set<int32_t>& newSuppressedPointerIds) {
+    LOG_ALWAYS_FATAL_IF(args.pointerCount == 0, "0 pointers in %s", args.dump().c_str());
+
+    // First, let's remove the old suppressed pointers. They've already been canceled previously.
+    NotifyMotionArgs oldArgs = removePointerIds(args, oldSuppressedPointerIds);
+
+    // Cancel any newly suppressed pointers.
+    std::vector<NotifyMotionArgs> out;
+    const int32_t activePointerId =
+            args.pointerProperties[MotionEvent::getActionIndex(args.action)].id;
+    const int32_t actionMasked = MotionEvent::getActionMasked(args.action);
+    // We will iteratively remove pointers from 'removedArgs'.
+    NotifyMotionArgs removedArgs{oldArgs};
+    for (uint32_t i = 0; i < oldArgs.pointerCount; i++) {
+        const int32_t pointerId = oldArgs.pointerProperties[i].id;
+        if (newSuppressedPointerIds.find(pointerId) == newSuppressedPointerIds.end()) {
+            // This is a pointer that should not be canceled. Move on.
+            continue;
+        }
+        if (pointerId == activePointerId && actionMasked == AMOTION_EVENT_ACTION_POINTER_DOWN) {
+            // Remove this pointer, but don't cancel it. We'll just not send the POINTER_DOWN event
+            removedArgs = removePointerIds(removedArgs, {pointerId});
+            continue;
+        }
+
+        if (removedArgs.pointerCount == 1) {
+            // We are about to remove the last pointer, which means there will be no more gesture
+            // remaining. This is identical to canceling all pointers, so just send a single CANCEL
+            // event, without any of the preceding POINTER_UP with FLAG_CANCELED events.
+            oldArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
+            oldArgs.action = AMOTION_EVENT_ACTION_CANCEL;
+            return {oldArgs};
+        }
+        // Cancel the current pointer
+        out.push_back(removedArgs);
+        out.back().flags |= AMOTION_EVENT_FLAG_CANCELED;
+        out.back().action = getActionUpForPointerId(out.back(), pointerId);
+
+        // Remove the newly canceled pointer from the args
+        removedArgs = removePointerIds(removedArgs, {pointerId});
+    }
+
+    // Now 'removedArgs' contains only pointers that are valid.
+    if (removedArgs.pointerCount <= 0 || removedArgs.action == ACTION_UNKNOWN) {
+        return out;
+    }
+    out.push_back(removedArgs);
+    return out;
+}
+
+UnwantedInteractionBlocker::UnwantedInteractionBlocker(InputListenerInterface& listener)
+      : UnwantedInteractionBlocker(listener, isPalmRejectionEnabled()){};
+
+UnwantedInteractionBlocker::UnwantedInteractionBlocker(InputListenerInterface& listener,
+                                                       bool enablePalmRejection)
+      : mListener(listener), mEnablePalmRejection(enablePalmRejection) {}
+
+void UnwantedInteractionBlocker::notifyConfigurationChanged(
+        const NotifyConfigurationChangedArgs* args) {
+    mListener.notifyConfigurationChanged(args);
+}
+
+void UnwantedInteractionBlocker::notifyKey(const NotifyKeyArgs* args) {
+    mListener.notifyKey(args);
+}
+
+void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs* args) {
+    auto it = mPalmRejectors.find(args->deviceId);
+    const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args->source);
+    if (!sendToPalmRejector) {
+        mListener.notifyMotion(args);
+        return;
+    }
+
+    const std::vector<NotifyMotionArgs> newMotions = it->second.processMotion(*args);
+    for (const NotifyMotionArgs& newArgs : newMotions) {
+        mListener.notifyMotion(&newArgs);
+    }
+}
+
+void UnwantedInteractionBlocker::notifySwitch(const NotifySwitchArgs* args) {
+    mListener.notifySwitch(args);
+}
+
+void UnwantedInteractionBlocker::notifySensor(const NotifySensorArgs* args) {
+    mListener.notifySensor(args);
+}
+
+void UnwantedInteractionBlocker::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+    mListener.notifyVibratorState(args);
+}
+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);
+}
+
+void UnwantedInteractionBlocker::notifyPointerCaptureChanged(
+        const NotifyPointerCaptureChangedArgs* args) {
+    mListener.notifyPointerCaptureChanged(args);
+}
+
+void UnwantedInteractionBlocker::notifyInputDevicesChanged(
+        const std::vector<InputDeviceInfo>& inputDevices) {
+    if (!mEnablePalmRejection) {
+        // Palm rejection is disabled. Don't create any palm rejector objects.
+        return;
+    }
+
+    // Let's see which of the existing devices didn't change, so that we can keep them
+    // and prevent event stream disruption
+    std::set<int32_t /*deviceId*/> devicesToKeep;
+    for (const InputDeviceInfo& device : inputDevices) {
+        std::optional<AndroidPalmFilterDeviceInfo> info = createPalmFilterDeviceInfo(device);
+        if (!info) {
+            continue;
+        }
+
+        auto [it, emplaced] = mPalmRejectors.try_emplace(device.getId(), *info);
+        if (!emplaced && *info != it->second.getPalmFilterDeviceInfo()) {
+            // Re-create the PalmRejector because the device info has changed.
+            mPalmRejectors.erase(it);
+            mPalmRejectors.emplace(device.getId(), *info);
+        }
+        devicesToKeep.insert(device.getId());
+    }
+    // Delete all devices that we don't need to keep
+    std::erase_if(mPalmRejectors, [&devicesToKeep](const auto& item) {
+        auto const& [deviceId, _] = item;
+        return devicesToKeep.find(deviceId) == devicesToKeep.end();
+    });
+}
+
+void UnwantedInteractionBlocker::dump(std::string& dump) {
+    dump += "UnwantedInteractionBlocker:\n";
+    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(), "      ");
+    }
+}
+
+void UnwantedInteractionBlocker::monitor() {}
+
+UnwantedInteractionBlocker::~UnwantedInteractionBlocker() {}
+
+void SlotState::update(const NotifyMotionArgs& args) {
+    for (size_t i = 0; i < args.pointerCount; i++) {
+        const int32_t pointerId = args.pointerProperties[i].id;
+        const int32_t resolvedAction = resolveActionForPointer(i, args.action);
+        processPointerId(pointerId, resolvedAction);
+    }
+}
+
+size_t SlotState::findUnusedSlot() const {
+    size_t unusedSlot = 0;
+    // Since the collection is ordered, we can rely on the in-order traversal
+    for (const auto& [slot, trackingId] : mPointerIdsBySlot) {
+        if (unusedSlot != slot) {
+            break;
+        }
+        unusedSlot++;
+    }
+    return unusedSlot;
+}
+
+void SlotState::processPointerId(int pointerId, int32_t actionMasked) {
+    switch (MotionEvent::getActionMasked(actionMasked)) {
+        case AMOTION_EVENT_ACTION_DOWN:
+        case AMOTION_EVENT_ACTION_POINTER_DOWN:
+        case AMOTION_EVENT_ACTION_HOVER_ENTER: {
+            // New pointer going down
+            size_t newSlot = findUnusedSlot();
+            mPointerIdsBySlot[newSlot] = pointerId;
+            mSlotsByPointerId[pointerId] = newSlot;
+            return;
+        }
+        case AMOTION_EVENT_ACTION_MOVE:
+        case AMOTION_EVENT_ACTION_HOVER_MOVE: {
+            return;
+        }
+        case AMOTION_EVENT_ACTION_CANCEL:
+        case AMOTION_EVENT_ACTION_POINTER_UP:
+        case AMOTION_EVENT_ACTION_UP:
+        case AMOTION_EVENT_ACTION_HOVER_EXIT: {
+            auto it = mSlotsByPointerId.find(pointerId);
+            LOG_ALWAYS_FATAL_IF(it == mSlotsByPointerId.end());
+            size_t slot = it->second;
+            // Erase this pointer from both collections
+            mPointerIdsBySlot.erase(slot);
+            mSlotsByPointerId.erase(pointerId);
+            return;
+        }
+    }
+    LOG_ALWAYS_FATAL("Unhandled action : %s", MotionEvent::actionToString(actionMasked).c_str());
+    return;
+}
+
+std::optional<size_t> SlotState::getSlotForPointerId(int32_t pointerId) const {
+    auto it = mSlotsByPointerId.find(pointerId);
+    if (it == mSlotsByPointerId.end()) {
+        return std::nullopt;
+    }
+    return it->second;
+}
+
+std::string SlotState::dump() const {
+    std::string out = "mSlotsByPointerId:\n";
+    out += addPrefix(dumpMap(mSlotsByPointerId), "  ") + "\n";
+    out += "mPointerIdsBySlot:\n";
+    out += addPrefix(dumpMap(mPointerIdsBySlot), "  ") + "\n";
+    return out;
+}
+
+PalmRejector::PalmRejector(const AndroidPalmFilterDeviceInfo& info,
+                           std::unique_ptr<::ui::PalmDetectionFilter> filter)
+      : mSharedPalmState(std::make_unique<::ui::SharedPalmDetectionFilterState>()),
+        mDeviceInfo(info),
+        mPalmDetectionFilter(std::move(filter)) {
+    if (mPalmDetectionFilter != nullptr) {
+        // This path is used for testing. Non-testing invocations should let this constructor
+        // create a real PalmDetectionFilter
+        return;
+    }
+    std::unique_ptr<::ui::NeuralStylusPalmDetectionFilterModel> model =
+            std::make_unique<::ui::OneDeviceTrainNeuralStylusPalmDetectionFilterModel>(
+                    std::vector<float>());
+    mPalmDetectionFilter =
+            std::make_unique<::ui::NeuralStylusPalmDetectionFilter>(mDeviceInfo, std::move(model),
+                                                                    mSharedPalmState.get());
+}
+
+std::vector<::ui::InProgressTouchEvdev> getTouches(const NotifyMotionArgs& args,
+                                                   const AndroidPalmFilterDeviceInfo& deviceInfo,
+                                                   const SlotState& oldSlotState,
+                                                   const SlotState& newSlotState) {
+    std::vector<::ui::InProgressTouchEvdev> touches;
+
+    for (size_t i = 0; i < args.pointerCount; i++) {
+        const int32_t pointerId = args.pointerProperties[i].id;
+        touches.emplace_back(::ui::InProgressTouchEvdev());
+        touches.back().major = args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR);
+        touches.back().minor = args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR);
+        touches.back().tool_type = getLinuxToolType(args.pointerProperties[i].toolType);
+
+        // Whether there is new information for the touch.
+        touches.back().altered = true;
+
+        // Whether the touch was cancelled. Touch events should be ignored till a
+        // new touch is initiated.
+        touches.back().was_cancelled = false;
+
+        // Whether the touch is going to be canceled.
+        touches.back().cancelled = false;
+
+        // Whether the touch is delayed at first appearance. Will not be reported yet.
+        touches.back().delayed = false;
+
+        // Whether the touch was delayed before.
+        touches.back().was_delayed = false;
+
+        // Whether the touch is held until end or no longer held.
+        touches.back().held = false;
+
+        // Whether this touch was held before being sent.
+        touches.back().was_held = false;
+
+        const int32_t resolvedAction = resolveActionForPointer(i, args.action);
+        const bool isDown = resolvedAction == AMOTION_EVENT_ACTION_POINTER_DOWN ||
+                resolvedAction == AMOTION_EVENT_ACTION_DOWN;
+        touches.back().was_touching = !isDown;
+
+        const bool isUpOrCancel = resolvedAction == AMOTION_EVENT_ACTION_CANCEL ||
+                resolvedAction == AMOTION_EVENT_ACTION_UP ||
+                resolvedAction == AMOTION_EVENT_ACTION_POINTER_UP;
+
+        touches.back().x = args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X);
+        touches.back().y = args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y);
+
+        std::optional<size_t> slot = newSlotState.getSlotForPointerId(pointerId);
+        if (!slot) {
+            slot = oldSlotState.getSlotForPointerId(pointerId);
+        }
+        LOG_ALWAYS_FATAL_IF(!slot, "Could not find slot for pointer %d", pointerId);
+        touches.back().slot = *slot;
+        touches.back().tracking_id = (!isUpOrCancel) ? pointerId : -1;
+        touches.back().touching = !isUpOrCancel;
+
+        // The fields 'radius_x' and 'radius_x' are not used for palm rejection
+        touches.back().pressure = args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
+        touches.back().tool_code = BTN_TOOL_FINGER;
+        // The field 'orientation' is not used for palm rejection
+        // The fields 'tilt_x' and 'tilt_y' are not used for palm rejection
+        touches.back().reported_tool_type = ::ui::EventPointerType::kTouch;
+        touches.back().stylus_button = false;
+    }
+    return touches;
+}
+
+std::vector<NotifyMotionArgs> PalmRejector::processMotion(const NotifyMotionArgs& args) {
+    if (mPalmDetectionFilter == nullptr) {
+        return {args};
+    }
+    const bool skipThisEvent = args.action == AMOTION_EVENT_ACTION_HOVER_ENTER ||
+            args.action == AMOTION_EVENT_ACTION_HOVER_MOVE ||
+            args.action == AMOTION_EVENT_ACTION_HOVER_EXIT ||
+            args.action == AMOTION_EVENT_ACTION_BUTTON_PRESS ||
+            args.action == AMOTION_EVENT_ACTION_BUTTON_RELEASE ||
+            args.action == AMOTION_EVENT_ACTION_SCROLL;
+    if (skipThisEvent) {
+        // Lets not process hover events, button events, or scroll for now.
+        return {args};
+    }
+    if (args.action == AMOTION_EVENT_ACTION_DOWN) {
+        mSuppressedPointerIds.clear();
+    }
+    std::bitset<::ui::kNumTouchEvdevSlots> slotsToHold;
+    std::bitset<::ui::kNumTouchEvdevSlots> slotsToSuppress;
+
+    // Store the slot state before we call getTouches and update it. This way, we can find
+    // the slots that have been removed due to the incoming event.
+    SlotState oldSlotState = mSlotState;
+    mSlotState.update(args);
+    std::vector<::ui::InProgressTouchEvdev> touches =
+            getTouches(args, mDeviceInfo, oldSlotState, mSlotState);
+    ::base::TimeTicks chromeTimestamp = toChromeTimestamp(args.eventTime);
+
+    mPalmDetectionFilter->Filter(touches, chromeTimestamp, &slotsToHold, &slotsToSuppress);
+
+    // Now that we know which slots should be suppressed, let's convert those to pointer id's.
+    std::set<int32_t> oldSuppressedIds;
+    std::swap(oldSuppressedIds, mSuppressedPointerIds);
+    for (size_t i = 0; i < args.pointerCount; i++) {
+        const int32_t pointerId = args.pointerProperties[i].id;
+        std::optional<size_t> slot = oldSlotState.getSlotForPointerId(pointerId);
+        if (!slot) {
+            slot = mSlotState.getSlotForPointerId(pointerId);
+            LOG_ALWAYS_FATAL_IF(!slot, "Could not find slot for pointer id %" PRId32, pointerId);
+        }
+        if (slotsToSuppress.test(*slot)) {
+            mSuppressedPointerIds.insert(pointerId);
+        }
+    }
+
+    std::vector<NotifyMotionArgs> argsWithoutUnwantedPointers =
+            cancelSuppressedPointers(args, oldSuppressedIds, mSuppressedPointerIds);
+    for (const NotifyMotionArgs& checkArgs : argsWithoutUnwantedPointers) {
+        LOG_ALWAYS_FATAL_IF(checkArgs.action == ACTION_UNKNOWN, "%s", checkArgs.dump().c_str());
+    }
+
+    if (mSuppressedPointerIds != oldSuppressedIds) {
+        if (argsWithoutUnwantedPointers.size() != 1 ||
+            argsWithoutUnwantedPointers[0].pointerCount != args.pointerCount) {
+            ALOGI("Palm detected, removing pointer ids %s from %s",
+                  dumpSet(mSuppressedPointerIds).c_str(), args.dump().c_str());
+        }
+    }
+
+    return argsWithoutUnwantedPointers;
+}
+
+const AndroidPalmFilterDeviceInfo& PalmRejector::getPalmFilterDeviceInfo() {
+    return mDeviceInfo;
+}
+
+std::string PalmRejector::dump() const {
+    std::string out;
+    out += "mDeviceInfo:\n";
+    out += addPrefix(dumpDeviceInfo(mDeviceInfo), "  ");
+    out += "mSlotState:\n";
+    out += addPrefix(mSlotState.dump(), "  ");
+    out += "mSuppressedPointerIds: ";
+    out += dumpSet(mSuppressedPointerIds) + "\n";
+    return out;
+}
+
+} // namespace android
diff --git a/services/inputflinger/UnwantedInteractionBlocker.h b/services/inputflinger/UnwantedInteractionBlocker.h
new file mode 100644
index 0000000..14068fd
--- /dev/null
+++ b/services/inputflinger/UnwantedInteractionBlocker.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <map>
+#include <set>
+
+#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"
+
+namespace android {
+
+// --- Functions for manipulation of event streams
+
+struct AndroidPalmFilterDeviceInfo : ::ui::PalmFilterDeviceInfo {
+    // Additional fields from 'TouchEventConverterEvdev', added here for convenience
+    int32_t touch_major_res = 1; // info.GetAbsInfoByCode(ABS_MT_TOUCH_MAJOR).resolution;
+    int32_t touch_minor_res = 1; // info.GetAbsInfoByCode(ABS_MT_TOUCH_MINOR).resolution;
+
+    auto operator<=>(const AndroidPalmFilterDeviceInfo&) const = default;
+};
+
+std::optional<AndroidPalmFilterDeviceInfo> createPalmFilterDeviceInfo(
+        const InputDeviceInfo& deviceInfo);
+
+static constexpr int32_t ACTION_UNKNOWN = -1;
+
+NotifyMotionArgs removePointerIds(const NotifyMotionArgs& args,
+                                  const std::set<int32_t>& pointerIds);
+
+std::vector<NotifyMotionArgs> cancelSuppressedPointers(
+        const NotifyMotionArgs& args, const std::set<int32_t>& oldSuppressedPointerIds,
+        const std::set<int32_t>& newSuppressedPointerIds);
+
+std::string toString(const ::ui::InProgressTouchEvdev& touch);
+
+// --- Main classes and interfaces ---
+
+class PalmRejector;
+
+// --- Implementations ---
+
+/**
+ * Implementation of the UnwantedInteractionBlockerInterface.
+ * Represents a separate stage of input processing. All of the input events go through this stage.
+ * Acts as a passthrough for all input events except for motion events.
+ *
+ * The events of motion type are sent to PalmRejectors. PalmRejectors detect unwanted touches,
+ * and emit input streams with the bad pointers removed.
+ */
+class UnwantedInteractionBlocker : public UnwantedInteractionBlockerInterface {
+public:
+    explicit UnwantedInteractionBlocker(InputListenerInterface& listener);
+    explicit UnwantedInteractionBlocker(InputListenerInterface& listener, bool enablePalmRejection);
+
+    void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+    void notifyKey(const NotifyKeyArgs* args) override;
+    void notifyMotion(const NotifyMotionArgs* args) override;
+    void notifySwitch(const NotifySwitchArgs* args) override;
+    void notifySensor(const NotifySensorArgs* args) override;
+    void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
+    void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+    void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+
+    void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override;
+    void dump(std::string& dump) override;
+    void monitor() override;
+
+    ~UnwantedInteractionBlocker();
+
+private:
+    // The next stage to pass input events to
+    InputListenerInterface& mListener;
+    const bool mEnablePalmRejection;
+
+    // Detect and reject unwanted palms on screen
+    // Use a separate palm rejector for every touch device.
+    std::map<int32_t /*deviceId*/, PalmRejector> mPalmRejectors;
+};
+
+class SlotState {
+public:
+    /**
+     * Update the state using the new information provided in the NotifyMotionArgs
+     */
+    void update(const NotifyMotionArgs& args);
+    std::optional<size_t> getSlotForPointerId(int32_t pointerId) const;
+    std::string dump() const;
+
+private:
+    // Process a pointer with the provided action, and return the slot associated with it
+    void processPointerId(int32_t pointerId, int32_t action);
+    // The map from tracking id to slot state. Since the PalmRejectionFilter works close to the
+    // evdev level, the only way to tell it about UP or CANCEL events is by sending tracking id = -1
+    // to the appropriate touch slot. So we need to reconstruct the original slot.
+    // The two collections below must always be in-sync.
+    // Use std::map instead of std::unordered_map because we rely on these collections being
+    // ordered. It also has better space efficiency than unordered_map because we only have a few
+    // pointers most of the time.
+    std::map<int32_t /*pointerId*/, size_t /*slot*/> mSlotsByPointerId;
+    std::map<size_t /*slot*/, int32_t /*pointerId */> mPointerIdsBySlot;
+
+    size_t findUnusedSlot() const;
+};
+
+/**
+ * Convert an Android event to a linux-like 'InProgressTouchEvdev'. The provided SlotState's
+ * are used to figure out which slot does each pointer belong to.
+ */
+std::vector<::ui::InProgressTouchEvdev> getTouches(const NotifyMotionArgs& args,
+                                                   const AndroidPalmFilterDeviceInfo& deviceInfo,
+                                                   const SlotState& oldSlotState,
+                                                   const SlotState& newSlotState);
+
+class PalmRejector {
+public:
+    explicit PalmRejector(const AndroidPalmFilterDeviceInfo& info,
+                          std::unique_ptr<::ui::PalmDetectionFilter> filter = nullptr);
+    std::vector<NotifyMotionArgs> processMotion(const NotifyMotionArgs& args);
+
+    // Get the device info of this device, for comparison purposes
+    const AndroidPalmFilterDeviceInfo& getPalmFilterDeviceInfo();
+    std::string dump() const;
+
+private:
+    PalmRejector(const PalmRejector&) = delete;
+    PalmRejector& operator=(const PalmRejector&) = delete;
+
+    std::unique_ptr<::ui::SharedPalmDetectionFilterState> mSharedPalmState;
+    AndroidPalmFilterDeviceInfo mDeviceInfo;
+    std::unique_ptr<::ui::PalmDetectionFilter> mPalmDetectionFilter;
+    std::set<int32_t> mSuppressedPointerIds;
+
+    // Used to help convert an Android touch stream to Linux input stream.
+    SlotState mSlotState;
+};
+
+} // namespace android
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index db63104..dff5894 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -142,6 +142,8 @@
     bool operator==(const NotifyMotionArgs& rhs) const;
 
     void notify(InputListenerInterface& listener) const override;
+
+    std::string dump() const;
 };
 
 /* Describes a sensor event. */
diff --git a/services/inputflinger/include/UnwantedInteractionBlockerInterface.h b/services/inputflinger/include/UnwantedInteractionBlockerInterface.h
new file mode 100644
index 0000000..2327266
--- /dev/null
+++ b/services/inputflinger/include/UnwantedInteractionBlockerInterface.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "InputListener.h"
+
+namespace android {
+
+/**
+ * Base interface for an InputListener stage.
+ * Blocks unintentional input events. Not thread safe. Must be called from the same
+ * thread. All work is performed on the calling threads.
+ */
+class UnwantedInteractionBlockerInterface : public InputListenerInterface {
+public:
+    /* Notifies the input reader policy that some input devices have changed
+     * and provides information about all current input devices.
+     * Important! This call should happen on the same thread as the calls to the
+     * InputListenerInterface methods.
+     * That is, same thread should call 'notifyMotion' and 'notifyInputDevicesChanged' and
+     * 'notifyDeviceReset'. If this architecture changes, we will need to make the implementation
+     * of this interface thread-safe.
+     */
+    virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) = 0;
+
+    /**
+     * Dump the state of the interaction blocker.
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void dump(std::string& dump) = 0;
+
+    /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */
+    virtual void monitor() = 0;
+
+    UnwantedInteractionBlockerInterface() {}
+    ~UnwantedInteractionBlockerInterface() override {}
+};
+
+} // namespace android
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index d19dbaf..f734e59 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -49,6 +49,7 @@
         "LatencyTracker_test.cpp",
         "TestInputListener.cpp",
         "UinputDevice.cpp",
+        "UnwantedInteractionBlocker_test.cpp",
     ],
     aidl: {
         include_dirs: [
diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
new file mode 100644
index 0000000..a3220cc
--- /dev/null
+++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
@@ -0,0 +1,938 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../UnwantedInteractionBlocker.h"
+#include <android-base/silent_death_test.h>
+#include <gtest/gtest.h>
+#include <gui/constants.h>
+#include <linux/input.h>
+
+#include "TestInputListener.h"
+
+namespace android {
+
+constexpr int32_t DEVICE_ID = 3;
+constexpr int32_t X_RESOLUTION = 11;
+constexpr int32_t Y_RESOLUTION = 11;
+constexpr int32_t MAJOR_RESOLUTION = 1;
+
+constexpr int POINTER_0_DOWN =
+        AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+constexpr int POINTER_1_DOWN =
+        AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+constexpr int POINTER_2_DOWN =
+        AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+constexpr int POINTER_0_UP =
+        AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+constexpr int POINTER_1_UP =
+        AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+constexpr int POINTER_2_UP =
+        AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+constexpr int DOWN = AMOTION_EVENT_ACTION_DOWN;
+constexpr int MOVE = AMOTION_EVENT_ACTION_MOVE;
+constexpr int UP = AMOTION_EVENT_ACTION_UP;
+constexpr int CANCEL = AMOTION_EVENT_ACTION_CANCEL;
+
+struct PointerData {
+    float x;
+    float y;
+    float major;
+};
+
+static NotifyMotionArgs generateMotionArgs(nsecs_t downTime, nsecs_t eventTime, int32_t action,
+                                           const std::vector<PointerData>& points) {
+    size_t pointerCount = points.size();
+    if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
+        EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
+    }
+
+    PointerProperties pointerProperties[pointerCount];
+    PointerCoords pointerCoords[pointerCount];
+
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerProperties[i].id = i;
+        pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+
+        pointerCoords[i].clear();
+        pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
+        pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
+        pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, points[i].major);
+    }
+
+    // Define a valid motion event.
+    NotifyMotionArgs args(/* id */ 0, eventTime, 0 /*readTime*/, DEVICE_ID,
+                          AINPUT_SOURCE_TOUCHSCREEN, 0 /*displayId*/, POLICY_FLAG_PASS_TO_USER,
+                          action, /* actionButton */ 0,
+                          /* flags */ 0, AMETA_NONE, /* buttonState */ 0,
+                          MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount,
+                          pointerProperties, pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                          AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime, /* videoFrames */ {});
+
+    return args;
+}
+
+static InputDeviceInfo generateTestDeviceInfo() {
+    InputDeviceIdentifier identifier;
+
+    auto info = InputDeviceInfo();
+    info.initialize(DEVICE_ID, /*generation*/ 1, /*controllerNumber*/ 1, identifier, "alias",
+                    /*isExternal*/ false, /*hasMic*/ false);
+    info.addSource(AINPUT_SOURCE_TOUCHSCREEN);
+    info.addMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN, 0, 1599, /*flat*/ 0,
+                        /*fuzz*/ 0, X_RESOLUTION);
+    info.addMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN, 0, 2559, /*flat*/ 0,
+                        /*fuzz*/ 0, Y_RESOLUTION);
+    info.addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR, AINPUT_SOURCE_TOUCHSCREEN, 0, 255,
+                        /*flat*/ 0, /*fuzz*/ 0, MAJOR_RESOLUTION);
+
+    return info;
+}
+
+static AndroidPalmFilterDeviceInfo generatePalmFilterDeviceInfo() {
+    InputDeviceInfo androidInfo = generateTestDeviceInfo();
+    std::optional<AndroidPalmFilterDeviceInfo> info = createPalmFilterDeviceInfo(androidInfo);
+    if (!info) {
+        ADD_FAILURE() << "Could not convert android device info to ::ui version";
+        return {};
+    }
+    return *info;
+}
+
+TEST(DeviceInfoConversionTest, TabletDeviceTest) {
+    AndroidPalmFilterDeviceInfo info = generatePalmFilterDeviceInfo();
+    ASSERT_EQ(X_RESOLUTION, info.x_res);
+    ASSERT_EQ(Y_RESOLUTION, info.y_res);
+    ASSERT_EQ(MAJOR_RESOLUTION, info.touch_major_res);
+    ASSERT_EQ(1599, info.max_x);
+    ASSERT_EQ(2559, info.max_y);
+}
+
+static void assertArgs(const NotifyMotionArgs& args, int32_t action,
+                       const std::vector<std::pair<int32_t /*pointerId*/, PointerData>>& pointers) {
+    ASSERT_EQ(action, args.action);
+    ASSERT_EQ(pointers.size(), args.pointerCount);
+    for (size_t i = 0; i < args.pointerCount; i++) {
+        const auto& [pointerId, pointerData] = pointers[i];
+        ASSERT_EQ(pointerId, args.pointerProperties[i].id);
+        ASSERT_EQ(pointerData.x, args.pointerCoords[i].getX());
+        ASSERT_EQ(pointerData.y, args.pointerCoords[i].getY());
+        ASSERT_EQ(pointerData.major,
+                  args.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR));
+    }
+}
+
+TEST(RemovePointerIdsTest, RemoveOnePointer) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0,
+                                               AMOTION_EVENT_ACTION_MOVE, {{1, 2, 3}, {4, 5, 6}});
+
+    NotifyMotionArgs pointer1Only = removePointerIds(args, {0});
+    assertArgs(pointer1Only, AMOTION_EVENT_ACTION_MOVE, {{1, {4, 5, 6}}});
+
+    NotifyMotionArgs pointer0Only = removePointerIds(args, {1});
+    assertArgs(pointer0Only, AMOTION_EVENT_ACTION_MOVE, {{0, {1, 2, 3}}});
+}
+
+/**
+ * Remove 2 out of 3 pointers during a MOVE event.
+ */
+TEST(RemovePointerIdsTest, RemoveTwoPointers) {
+    NotifyMotionArgs args =
+            generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, AMOTION_EVENT_ACTION_MOVE,
+                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+
+    NotifyMotionArgs pointer1Only = removePointerIds(args, {0, 2});
+    assertArgs(pointer1Only, AMOTION_EVENT_ACTION_MOVE, {{1, {4, 5, 6}}});
+}
+
+/**
+ * Remove an active pointer during a POINTER_DOWN event, and also remove a non-active
+ * pointer during a POINTER_DOWN event.
+ */
+TEST(RemovePointerIdsTest, ActionPointerDown) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, POINTER_1_DOWN,
+                                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+
+    NotifyMotionArgs pointers0And2 = removePointerIds(args, {1});
+    assertArgs(pointers0And2, ACTION_UNKNOWN, {{0, {1, 2, 3}}, {2, {7, 8, 9}}});
+
+    NotifyMotionArgs pointers1And2 = removePointerIds(args, {0});
+    assertArgs(pointers1And2, POINTER_0_DOWN, {{1, {4, 5, 6}}, {2, {7, 8, 9}}});
+}
+
+/**
+ * Remove all pointers during a MOVE event.
+ */
+TEST(RemovePointerIdsTest, RemoveAllPointersDuringMove) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0,
+                                               AMOTION_EVENT_ACTION_MOVE, {{1, 2, 3}, {4, 5, 6}});
+
+    NotifyMotionArgs noPointers = removePointerIds(args, {0, 1});
+    ASSERT_EQ(0u, noPointers.pointerCount);
+}
+
+/**
+ * If we have ACTION_POINTER_DOWN, and we remove all pointers except for the active pointer,
+ * then we should just have ACTION_DOWN. Likewise, a POINTER_UP event should become an UP event.
+ */
+TEST(RemovePointerIdsTest, PointerDownBecomesDown) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, POINTER_1_DOWN,
+                                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+
+    NotifyMotionArgs pointer1 = removePointerIds(args, {0, 2});
+    assertArgs(pointer1, DOWN, {{1, {4, 5, 6}}});
+
+    args.action = POINTER_1_UP;
+    pointer1 = removePointerIds(args, {0, 2});
+    assertArgs(pointer1, UP, {{1, {4, 5, 6}}});
+}
+
+/**
+ * If a pointer that is now going down is canceled, then we can just drop the POINTER_DOWN event.
+ */
+TEST(CancelSuppressedPointersTest, CanceledPointerDownIsDropped) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, POINTER_1_DOWN,
+                                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {},
+                                     /*newSuppressedPointerIds*/ {1});
+    ASSERT_TRUE(result.empty());
+}
+
+/**
+ * If a pointer is already suppressed, the POINTER_UP event for this pointer should be dropped
+ */
+TEST(CancelSuppressedPointersTest, SuppressedPointerUpIsDropped) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, POINTER_1_UP,
+                                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {1},
+                                     /*newSuppressedPointerIds*/ {1});
+    ASSERT_TRUE(result.empty());
+}
+
+/**
+ * If a pointer is already suppressed, it should be removed from a MOVE event.
+ */
+TEST(CancelSuppressedPointersTest, SuppressedPointerIsRemovedDuringMove) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, MOVE,
+                                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {1},
+                                     /*newSuppressedPointerIds*/ {1});
+    ASSERT_EQ(1u, result.size());
+    assertArgs(result[0], MOVE, {{0, {1, 2, 3}}, {2, {7, 8, 9}}});
+}
+
+/**
+ * If a pointer just got canceled during a MOVE event, we should see two events:
+ * 1) ACTION_POINTER_UP with FLAG_CANCELED so that this pointer is lifted
+ * 2) A MOVE event without this pointer
+ */
+TEST(CancelSuppressedPointersTest, NewlySuppressedPointerIsCanceled) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, MOVE,
+                                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {},
+                                     /*newSuppressedPointerIds*/ {1});
+    ASSERT_EQ(2u, result.size());
+    assertArgs(result[0], POINTER_1_UP, {{0, {1, 2, 3}}, {1, {4, 5, 6}}, {2, {7, 8, 9}}});
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, result[0].flags);
+    assertArgs(result[1], MOVE, {{0, {1, 2, 3}}, {2, {7, 8, 9}}});
+}
+
+/**
+ * If we have a single pointer that gets canceled during a MOVE, the entire gesture
+ * should be canceled with ACTION_CANCEL.
+ */
+TEST(CancelSuppressedPointersTest, SingleSuppressedPointerIsCanceled) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, MOVE, {{1, 2, 3}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {},
+                                     /*newSuppressedPointerIds*/ {0});
+    ASSERT_EQ(1u, result.size());
+    assertArgs(result[0], CANCEL, {{0, {1, 2, 3}}});
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, result[0].flags);
+}
+
+/**
+ * If one of 3 pointers gets canceled during a POINTER_UP event, we should proceed with POINTER_UP,
+ * but this event should also have FLAG_CANCELED to indicate that this pointer was unintentional.
+ */
+TEST(CancelSuppressedPointersTest, SuppressedPointer1GoingUpIsCanceled) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, POINTER_1_UP,
+                                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {},
+                                     /*newSuppressedPointerIds*/ {1});
+    ASSERT_EQ(1u, result.size());
+    assertArgs(result[0], POINTER_1_UP, {{0, {1, 2, 3}}, {1, {4, 5, 6}}, {2, {7, 8, 9}}});
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, result[0].flags);
+}
+
+/**
+ * Same test as above, but we change the pointer's index to 0 instead of 1. This helps detect
+ * errors with handling pointer index inside the action.
+ */
+TEST(CancelSuppressedPointersTest, SuppressedPointer0GoingUpIsCanceled) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, POINTER_0_UP,
+                                               {{1, 2, 3}, {4, 5, 6}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {},
+                                     /*newSuppressedPointerIds*/ {0});
+    ASSERT_EQ(1u, result.size());
+    assertArgs(result[0], POINTER_0_UP, {{0, {1, 2, 3}}, {1, {4, 5, 6}}});
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, result[0].flags);
+}
+
+/**
+ * If two pointers are canceled simultaneously during MOVE, we should see a single ACTION_CANCEL
+ * event. This event would cancel the entire gesture.
+ */
+TEST(CancelSuppressedPointersTest, TwoNewlySuppressedPointersAreBothCanceled) {
+    NotifyMotionArgs args =
+            generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, MOVE, {{1, 2, 3}, {4, 5, 6}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {},
+                                     /*newSuppressedPointerIds*/ {0, 1});
+    ASSERT_EQ(1u, result.size());
+    assertArgs(result[0], CANCEL, {{0, {1, 2, 3}}, {1, {4, 5, 6}}});
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, result[0].flags);
+}
+
+/**
+ * Similar test to above. During a POINTER_UP event, both pointers are detected as 'palm' and
+ * therefore should be removed. In this case, we should send a single ACTION_CANCEL that
+ * would undo the entire gesture.
+ */
+TEST(CancelSuppressedPointersTest, TwoPointersAreCanceledDuringPointerUp) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, POINTER_1_UP,
+                                               {{1, 2, 3}, {4, 5, 6}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {1},
+                                     /*newSuppressedPointerIds*/ {0, 1});
+    ASSERT_EQ(1u, result.size());
+    assertArgs(result[0], CANCEL, {{0, {1, 2, 3}}});
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, result[0].flags);
+}
+
+/**
+ * When all pointers have been removed from the touch stream, and we have a new POINTER_DOWN,
+ * this should become a regular DOWN event because it's the only pointer that will be valid now.
+ */
+TEST(CancelSuppressedPointersTest, NewPointerDownBecomesDown) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, POINTER_2_DOWN,
+                                               {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
+    std::vector<NotifyMotionArgs> result =
+            cancelSuppressedPointers(args, /*oldSuppressedPointerIds*/ {0, 1},
+                                     /*newSuppressedPointerIds*/ {0, 1});
+    ASSERT_EQ(1u, result.size());
+    assertArgs(result[0], DOWN, {{2, {7, 8, 9}}});
+    ASSERT_EQ(0, result[0].flags);
+}
+
+/**
+ * Call 'getTouches' for a DOWN event and check that the resulting 'InProgressTouchEvdev'
+ * struct is populated as expected.
+ */
+TEST(GetTouchesTest, ConvertDownEvent) {
+    NotifyMotionArgs args = generateMotionArgs(/*downTime*/ 0, /*eventTime*/ 0, DOWN, {{1, 2, 3}});
+    AndroidPalmFilterDeviceInfo deviceInfo = generatePalmFilterDeviceInfo();
+    SlotState slotState;
+    SlotState oldSlotState = slotState;
+    slotState.update(args);
+    std::vector<::ui::InProgressTouchEvdev> touches =
+            getTouches(args, deviceInfo, oldSlotState, slotState);
+    ASSERT_EQ(1u, touches.size());
+    ::ui::InProgressTouchEvdev expected;
+
+    expected.major = 3;
+    expected.minor = 0;
+    expected.tool_type = MT_TOOL_FINGER;
+    expected.altered = true;
+    expected.was_cancelled = false;
+    expected.cancelled = false;
+    expected.delayed = false;
+    expected.was_delayed = false;
+    expected.held = false;
+    expected.was_held = false;
+    expected.was_touching = false;
+    expected.touching = true;
+    expected.x = 1;
+    expected.y = 2;
+    expected.tracking_id = 0;
+    std::optional<size_t> slot = slotState.getSlotForPointerId(0);
+    ASSERT_TRUE(slot);
+    expected.slot = *slot;
+    expected.pressure = 0;
+    expected.tool_code = BTN_TOOL_FINGER;
+    expected.reported_tool_type = ::ui::EventPointerType::kTouch;
+    expected.stylus_button = false;
+
+    ASSERT_EQ(expected, touches[0]) << toString(touches[0]);
+}
+
+// --- UnwantedInteractionBlockerTest ---
+
+class UnwantedInteractionBlockerTest : public testing::Test {
+protected:
+    TestInputListener mTestListener;
+    std::unique_ptr<UnwantedInteractionBlockerInterface> mBlocker;
+
+    void SetUp() override {
+        mBlocker = std::make_unique<UnwantedInteractionBlocker>(mTestListener,
+                                                                /*enablePalmRejection*/ true);
+    }
+};
+
+/**
+ * Create a basic configuration change and send it to input classifier.
+ * Expect that the event is received by the next input stage, unmodified.
+ */
+TEST_F(UnwantedInteractionBlockerTest, ConfigurationChangedIsPassedToNextListener) {
+    // Create a basic configuration change and send to classifier
+    NotifyConfigurationChangedArgs args(1 /*sequenceNum*/, 2 /*eventTime*/);
+
+    mBlocker->notifyConfigurationChanged(&args);
+    NotifyConfigurationChangedArgs outArgs;
+    ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyConfigurationChangedWasCalled(&outArgs));
+    ASSERT_EQ(args, outArgs);
+}
+
+/**
+ * Keys are not handled in 'UnwantedInteractionBlocker' and should be passed
+ * to next stage unmodified.
+ */
+TEST_F(UnwantedInteractionBlockerTest, KeyIsPassedToNextListener) {
+    // Create a basic key event and send to classifier
+    NotifyKeyArgs args(1 /*sequenceNum*/, 2 /*eventTime*/, 21 /*readTime*/, 3 /*deviceId*/,
+                       AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT, 0 /*policyFlags*/,
+                       AKEY_EVENT_ACTION_DOWN, 4 /*flags*/, AKEYCODE_HOME, 5 /*scanCode*/,
+                       AMETA_NONE, 6 /*downTime*/);
+
+    mBlocker->notifyKey(&args);
+    NotifyKeyArgs outArgs;
+    ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyKeyWasCalled(&outArgs));
+    ASSERT_EQ(args, outArgs);
+}
+
+/**
+ * Create a basic motion event. Since it's just a DOWN event, it should not
+ * be detected as palm and should be sent to the next listener stage
+ * unmodified.
+ */
+TEST_F(UnwantedInteractionBlockerTest, DownEventIsPassedToNextListener) {
+    NotifyMotionArgs motionArgs =
+            generateMotionArgs(0 /*downTime*/, 0 /*eventTime*/, DOWN, {{1, 2, 3}});
+    mBlocker->notifyMotion(&motionArgs);
+    NotifyMotionArgs args;
+    ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(motionArgs, args);
+}
+
+/**
+ * Create a basic switch event and send it to the UnwantedInteractionBlocker.
+ * Expect that the event is received by the next input stage, unmodified.
+ */
+TEST_F(UnwantedInteractionBlockerTest, SwitchIsPassedToNextListener) {
+    NotifySwitchArgs args(1 /*sequenceNum*/, 2 /*eventTime*/, 3 /*policyFlags*/, 4 /*switchValues*/,
+                          5 /*switchMask*/);
+
+    mBlocker->notifySwitch(&args);
+    NotifySwitchArgs outArgs;
+    ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifySwitchWasCalled(&outArgs));
+    ASSERT_EQ(args, outArgs);
+}
+
+/**
+ * Create a basic device reset event and send it to UnwantedInteractionBlocker.
+ * Expect that the event is received by the next input stage, unmodified.
+ */
+TEST_F(UnwantedInteractionBlockerTest, DeviceResetIsPassedToNextListener) {
+    NotifyDeviceResetArgs args(1 /*sequenceNum*/, 2 /*eventTime*/, DEVICE_ID);
+
+    mBlocker->notifyDeviceReset(&args);
+    NotifyDeviceResetArgs outArgs;
+    ASSERT_NO_FATAL_FAILURE(mTestListener.assertNotifyDeviceResetWasCalled(&outArgs));
+    ASSERT_EQ(args, outArgs);
+}
+
+/**
+ * The state should be reset when device reset happens. That means, we can reset in the middle of a
+ * gesture, and start a new stream. There should be no crash. If the state wasn't reset correctly,
+ * a crash due to inconsistent event stream could have occurred.
+ */
+TEST_F(UnwantedInteractionBlockerTest, NoCrashWhenResetHappens) {
+    NotifyMotionArgs args;
+    mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+    mBlocker->notifyMotion(
+            &(args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, DOWN, {{1, 2, 3}})));
+    mBlocker->notifyMotion(
+            &(args = generateMotionArgs(0 /*downTime*/, 2 /*eventTime*/, MOVE, {{4, 5, 6}})));
+    NotifyDeviceResetArgs resetArgs(1 /*sequenceNum*/, 3 /*eventTime*/, DEVICE_ID);
+    mBlocker->notifyDeviceReset(&resetArgs);
+    // Start a new gesture with a DOWN event, even though the previous event stream was incomplete.
+    mBlocker->notifyMotion(
+            &(args = generateMotionArgs(0 /*downTime*/, 4 /*eventTime*/, DOWN, {{7, 8, 9}})));
+}
+
+/**
+ * If input devices have changed, but the important device info that's used by the
+ * UnwantedInteractionBlocker has not changed, there should not be a reset.
+ */
+TEST_F(UnwantedInteractionBlockerTest, NoResetIfDeviceInfoChanges) {
+    NotifyMotionArgs args;
+    mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+    mBlocker->notifyMotion(
+            &(args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, DOWN, {{1, 2, 3}})));
+    mBlocker->notifyMotion(
+            &(args = generateMotionArgs(0 /*downTime*/, 2 /*eventTime*/, MOVE, {{4, 5, 6}})));
+
+    // Now pretend the device changed, even though nothing is different for DEVICE_ID in practice.
+    mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+
+    // The MOVE event continues the gesture that started before 'devices changed', so it should not
+    // cause a crash.
+    mBlocker->notifyMotion(
+            &(args = generateMotionArgs(0 /*downTime*/, 4 /*eventTime*/, MOVE, {{7, 8, 9}})));
+}
+
+using UnwantedInteractionBlockerTestDeathTest = UnwantedInteractionBlockerTest;
+
+/**
+ * The state should be reset when device reset happens. If we receive an inconsistent event after
+ * the reset happens, crash should occur.
+ */
+TEST_F(UnwantedInteractionBlockerTestDeathTest, InconsistentEventAfterResetCausesACrash) {
+    ScopedSilentDeath _silentDeath;
+    NotifyMotionArgs args;
+    mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+    mBlocker->notifyMotion(
+            &(args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, DOWN, {{1, 2, 3}})));
+    mBlocker->notifyMotion(
+            &(args = generateMotionArgs(0 /*downTime*/, 2 /*eventTime*/, MOVE, {{4, 5, 6}})));
+    NotifyDeviceResetArgs resetArgs(1 /*sequenceNum*/, 3 /*eventTime*/, DEVICE_ID);
+    mBlocker->notifyDeviceReset(&resetArgs);
+    // Sending MOVE without a DOWN -> should crash!
+    ASSERT_DEATH(
+            {
+                mBlocker->notifyMotion(&(args = generateMotionArgs(0 /*downTime*/, 4 /*eventTime*/,
+                                                                   MOVE, {{7, 8, 9}})));
+            },
+            "Could not find slot");
+}
+
+/**
+ * There should be a crash when an inconsistent event is received.
+ */
+TEST_F(UnwantedInteractionBlockerTestDeathTest, WhenMoveWithoutDownCausesACrash) {
+    ScopedSilentDeath _silentDeath;
+    NotifyMotionArgs args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, MOVE, {{1, 2, 3}});
+    mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+    ASSERT_DEATH({ mBlocker->notifyMotion(&args); }, "Could not find slot");
+}
+
+class PalmRejectorTest : public testing::Test {
+protected:
+    std::unique_ptr<PalmRejector> mPalmRejector;
+
+    void SetUp() override {
+        AndroidPalmFilterDeviceInfo info = generatePalmFilterDeviceInfo();
+        mPalmRejector = std::make_unique<PalmRejector>(info);
+    }
+};
+
+using PalmRejectorTestDeathTest = PalmRejectorTest;
+
+TEST_F(PalmRejectorTestDeathTest, InconsistentEventCausesACrash) {
+    ScopedSilentDeath _silentDeath;
+    constexpr nsecs_t downTime = 0;
+    NotifyMotionArgs args =
+            generateMotionArgs(downTime, 2 /*eventTime*/, MOVE, {{1406.0, 650.0, 52.0}});
+    ASSERT_DEATH({ mPalmRejector->processMotion(args); }, "Could not find slot");
+}
+
+/**
+ * Use PalmRejector with actual touchscreen data and real model.
+ * Two pointers that should both be classified as palms.
+ */
+TEST_F(PalmRejectorTest, TwoPointersAreCanceled) {
+    std::vector<NotifyMotionArgs> argsList;
+    constexpr nsecs_t downTime = 255955749837000;
+
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, downTime, DOWN, {{1342.0, 613.0, 79.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955759313000, MOVE, {{1406.0, 650.0, 52.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955766361000, MOVE, {{1429.0, 672.0, 46.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955775989000, MOVE, {{1417.0, 685.0, 41.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955775989000, POINTER_1_DOWN,
+                               {{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955783039000, MOVE,
+                               {{1414.0, 702.0, 41.0}, {1059.0, 731.0, 12.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955792536000, MOVE,
+                               {{1415.0, 719.0, 44.0}, {1060.0, 760.0, 11.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955799474000, MOVE,
+                               {{1421.0, 733.0, 42.0}, {1065.0, 769.0, 13.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955809177000, MOVE,
+                               {{1426.0, 742.0, 43.0}, {1068.0, 771.0, 13.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955816131000, MOVE,
+                               {{1430.0, 748.0, 45.0}, {1069.0, 772.0, 13.0}}));
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955825907000, MOVE,
+                               {{1432.0, 750.0, 44.0}, {1069.0, 772.0, 13.0}}));
+    ASSERT_EQ(1u, argsList.size());
+    ASSERT_EQ(0 /* No FLAG_CANCELED */, argsList[0].flags);
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955832736000, MOVE,
+                               {{1433.0, 751.0, 44.0}, {1070.0, 771.0, 13.0}}));
+    ASSERT_EQ(2u, argsList.size());
+    ASSERT_EQ(POINTER_0_UP, argsList[0].action);
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, argsList[0].flags);
+    ASSERT_EQ(MOVE, argsList[1].action);
+    ASSERT_EQ(1u, argsList[1].pointerCount);
+    ASSERT_EQ(0, argsList[1].flags);
+
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955842432000, MOVE,
+                               {{1433.0, 751.0, 42.0}, {1071.0, 770.0, 13.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955849380000, MOVE,
+                               {{1433.0, 751.0, 45.0}, {1072.0, 769.0, 13.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955859046000, MOVE,
+                               {{1433.0, 751.0, 43.0}, {1072.0, 768.0, 13.0}}));
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955869823000, MOVE,
+                               {{1433.0, 751.0, 45.0}, {1072.0, 767.0, 13.0}}));
+    ASSERT_EQ(1u, argsList.size());
+    ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, argsList[0].action);
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955875641000, MOVE,
+                               {{1433.0, 751.0, 43.0}, {1072.0, 766.0, 13.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955882693000, MOVE,
+                               {{1433.0, 750.0, 44.0}, {1072.0, 765.0, 13.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955892324000, MOVE,
+                               {{1433.0, 750.0, 42.0}, {1072.0, 763.0, 14.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955899425000, MOVE,
+                               {{1434.0, 750.0, 44.0}, {1073.0, 761.0, 14.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955909400000, MOVE,
+                               {{1435.0, 750.0, 43.0}, {1073.0, 759.0, 15.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955915885000, MOVE,
+                               {{1436.0, 750.0, 45.0}, {1074.0, 757.0, 15.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955925607000, MOVE,
+                               {{1436.0, 750.0, 44.0}, {1074.0, 755.0, 15.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955932580000, MOVE,
+                               {{1436.0, 750.0, 45.0}, {1074.0, 753.0, 15.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955942231000, MOVE,
+                               {{1436.0, 749.0, 44.0}, {1074.0, 751.0, 15.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955949204000, MOVE,
+                               {{1435.0, 748.0, 45.0}, {1074.0, 749.0, 15.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955959103000, MOVE,
+                               {{1434.0, 746.0, 44.0}, {1074.0, 747.0, 14.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955965884000, MOVE,
+                               {{1433.0, 744.0, 44.0}, {1075.0, 745.0, 14.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955975649000, MOVE,
+                               {{1431.0, 741.0, 43.0}, {1075.0, 742.0, 13.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955982537000, MOVE,
+                               {{1428.0, 738.0, 43.0}, {1076.0, 739.0, 12.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955992284000, MOVE,
+                               {{1400.0, 726.0, 54.0}, {1076.0, 739.0, 13.0}}));
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955999348000, POINTER_1_UP,
+                               {{1362.0, 716.0, 55.0}, {1076.0, 739.0, 13.0}}));
+    ASSERT_TRUE(argsList.empty());
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955999348000, MOVE, {{1362.0, 716.0, 55.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956008885000, MOVE, {{1347.0, 707.0, 54.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956015791000, MOVE, {{1340.0, 698.0, 54.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956025804000, MOVE, {{1338.0, 694.0, 55.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956032314000, MOVE, {{1336.0, 690.0, 53.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956042329000, MOVE, {{1334.0, 685.0, 47.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956048979000, MOVE, {{1333.0, 679.0, 46.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956058813000, MOVE, {{1332.0, 672.0, 45.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956065592000, MOVE, {{1333.0, 666.0, 40.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956075276000, MOVE, {{1336.0, 661.0, 24.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956082198000, MOVE, {{1338.0, 656.0, 16.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956092059000, MOVE, {{1341.0, 649.0, 1.0}}));
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255956098764000, UP, {{1341.0, 649.0, 1.0}}));
+    ASSERT_TRUE(argsList.empty());
+}
+
+/**
+ * A test implementation of PalmDetectionFilter that allows you to specify which pointer you want
+ * the model to consider 'suppressed'. The pointer is specified using its position (x, y).
+ * Current limitation:
+ *      Pointers may not cross each other in space during motion. Otherwise, any pointer with the
+ *      position matching the suppressed position will be considered "palm".
+ */
+class TestFilter : public ::ui::PalmDetectionFilter {
+public:
+    TestFilter(::ui::SharedPalmDetectionFilterState* state,
+               std::vector<std::pair<float, float>>& suppressedPointers)
+          : ::ui::PalmDetectionFilter(state), mSuppressedPointers(suppressedPointers) {}
+
+    void Filter(const std::vector<::ui::InProgressTouchEvdev>& touches, ::base::TimeTicks time,
+                std::bitset<::ui::kNumTouchEvdevSlots>* slots_to_hold,
+                std::bitset<::ui::kNumTouchEvdevSlots>* slots_to_suppress) override {
+        updateSuppressedSlots(touches);
+        *slots_to_suppress = mSuppressedSlots;
+    }
+
+    std::string FilterNameForTesting() const override { return "test filter"; }
+
+private:
+    void updateSuppressedSlots(const std::vector<::ui::InProgressTouchEvdev>& touches) {
+        for (::ui::InProgressTouchEvdev touch : touches) {
+            for (const auto& [x, y] : mSuppressedPointers) {
+                const float dx = (touch.x - x);
+                const float dy = (touch.y - y);
+                const float distanceSquared = dx * dx + dy * dy;
+                if (distanceSquared < 1) {
+                    mSuppressedSlots.set(touch.slot, true);
+                }
+            }
+        }
+    }
+
+    std::bitset<::ui::kNumTouchEvdevSlots> mSuppressedSlots;
+    std::vector<std::pair<float, float>>& mSuppressedPointers;
+};
+
+class PalmRejectorFakeFilterTest : public testing::Test {
+protected:
+    std::unique_ptr<PalmRejector> mPalmRejector;
+
+    void SetUp() override {
+        std::unique_ptr<::ui::PalmDetectionFilter> filter =
+                std::make_unique<TestFilter>(&mSharedPalmState, /*byref*/ mSuppressedPointers);
+        mPalmRejector =
+                std::make_unique<PalmRejector>(generatePalmFilterDeviceInfo(), std::move(filter));
+    }
+
+    void suppressPointerAtPosition(float x, float y) { mSuppressedPointers.push_back({x, y}); }
+
+private:
+    std::vector<std::pair<float, float>> mSuppressedPointers;
+    ::ui::SharedPalmDetectionFilterState mSharedPalmState; // unused, but we must retain ownership
+};
+
+/**
+ * When a MOVE event happens, the model identifies the pointer as palm. At that time, the palm
+ * rejector should send a POINTER_UP event for this pointer with FLAG_CANCELED, and subsequent
+ * events should have this pointer removed.
+ */
+TEST_F(PalmRejectorFakeFilterTest, OneOfTwoPointersIsCanceled) {
+    std::vector<NotifyMotionArgs> argsList;
+    constexpr nsecs_t downTime = 0;
+
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, downTime, DOWN, {{1342.0, 613.0, 79.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 1, POINTER_1_DOWN,
+                               {{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}}));
+    // Cancel the second pointer
+    suppressPointerAtPosition(1059, 731);
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955783039000, MOVE,
+                               {{1414.0, 702.0, 41.0}, {1059.0, 731.0, 12.0}}));
+    ASSERT_EQ(2u, argsList.size());
+    // First event - cancel pointer 1
+    ASSERT_EQ(POINTER_1_UP, argsList[0].action);
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, argsList[0].flags);
+    // Second event - send MOVE for the remaining pointer
+    ASSERT_EQ(MOVE, argsList[1].action);
+    ASSERT_EQ(0, argsList[1].flags);
+
+    // Future move events only contain 1 pointer, because the second pointer will continue
+    // to be suppressed
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955783039000, MOVE,
+                               {{1433.0, 751.0, 43.0}, {1072.0, 766.0, 13.0}}));
+    ASSERT_EQ(1u, argsList.size());
+    ASSERT_EQ(MOVE, argsList[0].action);
+    ASSERT_EQ(1u, argsList[0].pointerCount);
+    ASSERT_EQ(1433, argsList[0].pointerCoords[0].getX());
+    ASSERT_EQ(751, argsList[0].pointerCoords[0].getY());
+}
+
+/**
+ * Send two pointers, and suppress both of them. Check that ACTION_CANCEL is generated.
+ * Afterwards:
+ *  1) Future MOVE events are ignored.
+ *  2) When a new pointer goes down, ACTION_DOWN is generated
+ */
+TEST_F(PalmRejectorFakeFilterTest, NewDownEventAfterCancel) {
+    std::vector<NotifyMotionArgs> argsList;
+    constexpr nsecs_t downTime = 0;
+
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, downTime, DOWN, {{1342.0, 613.0, 79.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 1, POINTER_1_DOWN,
+                               {{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}}));
+    // Cancel both pointers
+    suppressPointerAtPosition(1059, 731);
+    suppressPointerAtPosition(1400, 680);
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 1, MOVE, {{1400, 680, 41}, {1059, 731, 10}}));
+    ASSERT_EQ(1u, argsList.size());
+    // Cancel all
+    ASSERT_EQ(CANCEL, argsList[0].action);
+    ASSERT_EQ(2u, argsList[0].pointerCount);
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, argsList[0].flags);
+
+    // Future move events are ignored
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955783039000, MOVE,
+                               {{1433.0, 751.0, 43.0}, {1072.0, 766.0, 13.0}}));
+    ASSERT_EQ(0u, argsList.size());
+
+    // When a new pointer goes down, a new DOWN event is generated
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955783039000, POINTER_2_DOWN,
+                               {{1433.0, 751.0, 43.0}, {1072.0, 766.0, 13.0}, {1000, 700, 10}}));
+    ASSERT_EQ(1u, argsList.size());
+    ASSERT_EQ(DOWN, argsList[0].action);
+    ASSERT_EQ(1u, argsList[0].pointerCount);
+    ASSERT_EQ(2, argsList[0].pointerProperties[0].id);
+}
+
+/**
+ * 2 pointers are classified as palm simultaneously. When they are later
+ * released by Android, make sure that we drop both of these POINTER_UP events.
+ * Since they are classified as palm at the same time, we just need to receive a single CANCEL
+ * event. From MotionEvent docs: """A pointer id remains valid until the pointer eventually goes up
+ * (indicated by ACTION_UP or ACTION_POINTER_UP) or when the gesture is canceled (indicated by
+ *  ACTION_CANCEL)."""
+ * This means that generating additional POINTER_UP events is not necessary.
+ * The risk here is that "oldSuppressedPointerIds" will not be correct, because it will update after
+ * each motion, but pointers are canceled one at a time by Android.
+ */
+TEST_F(PalmRejectorFakeFilterTest, TwoPointersCanceledWhenOnePointerGoesUp) {
+    std::vector<NotifyMotionArgs> argsList;
+    constexpr nsecs_t downTime = 0;
+
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, downTime, DOWN, {{1342.0, 613.0, 79.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, /*eventTime*/ 1, POINTER_1_DOWN,
+                               {{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}}));
+    // Suppress both pointers!!
+    suppressPointerAtPosition(1414, 702);
+    suppressPointerAtPosition(1059, 731);
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955783039000, POINTER_1_UP,
+                               {{1414.0, 702.0, 41.0}, {1059.0, 731.0, 12.0}}));
+    ASSERT_EQ(1u, argsList.size());
+    ASSERT_EQ(CANCEL, argsList[0].action) << MotionEvent::actionToString(argsList[0].action);
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, argsList[0].flags);
+
+    // Future move events should not go to the listener.
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955783049000, MOVE, {{1435.0, 755.0, 43.0}}));
+    ASSERT_EQ(0u, argsList.size());
+
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, 255955783059000, UP, {{1436.0, 756.0, 43.0}}));
+    ASSERT_EQ(0u, argsList.size());
+}
+
+/**
+ * Send 3 pointers, and then cancel one of them during a MOVE event. We should see ACTION_POINTER_UP
+ * generated for that. Next, another pointer is canceled during ACTION_POINTER_DOWN. For that
+ * pointer, we simply shouldn't send the event.
+ */
+TEST_F(PalmRejectorFakeFilterTest, CancelTwoPointers) {
+    std::vector<NotifyMotionArgs> argsList;
+    constexpr nsecs_t downTime = 0;
+
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, downTime, DOWN, {{1342.0, 613.0, 79.0}}));
+    mPalmRejector->processMotion(
+            generateMotionArgs(downTime, /*eventTime*/ 1, POINTER_1_DOWN,
+                               {{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}}));
+
+    // Suppress second pointer (pointer 1)
+    suppressPointerAtPosition(1060, 700);
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, /*eventTime*/ 1, MOVE,
+                               {{1417.0, 685.0, 41.0}, {1060, 700, 10.0}}));
+    ASSERT_EQ(2u, argsList.size());
+    ASSERT_EQ(POINTER_1_UP, argsList[0].action);
+    ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, argsList[0].flags);
+
+    ASSERT_EQ(MOVE, argsList[1].action) << MotionEvent::actionToString(argsList[1].action);
+    ASSERT_EQ(0, argsList[1].flags);
+
+    // A new pointer goes down and gets suppressed right away. It should just be dropped
+    suppressPointerAtPosition(1001, 601);
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, /*eventTime*/ 1, POINTER_2_DOWN,
+                               {{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}, {1001, 601, 5}}));
+
+    ASSERT_EQ(0u, argsList.size());
+    // Likewise, pointer that's already canceled should be ignored
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, /*eventTime*/ 1, POINTER_2_UP,
+                               {{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}, {1001, 601, 5}}));
+    ASSERT_EQ(0u, argsList.size());
+
+    // Cancel all pointers when pointer 1 goes up. Pointer 1 was already canceled earlier.
+    suppressPointerAtPosition(1417, 685);
+    argsList = mPalmRejector->processMotion(
+            generateMotionArgs(downTime, /*eventTime*/ 1, POINTER_1_UP,
+                               {{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}}));
+    ASSERT_EQ(1u, argsList.size());
+    ASSERT_EQ(CANCEL, argsList[0].action);
+}
+
+} // namespace android
