Merge "InputMapper refactor: KeyboardInputMapper" into udc-dev
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 9125fe4..bdd45dc 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2561,9 +2561,17 @@
         std::vector<TouchedWindow> hoveringWindows =
                 getHoveringWindowsLocked(oldState, tempTouchState, entry);
         for (const TouchedWindow& touchedWindow : hoveringWindows) {
-            addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
-                                  touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
-                                  targets);
+            std::optional<InputTarget> target =
+                    createInputTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
+                                            touchedWindow.firstDownTimeInTarget);
+            if (!target) {
+                continue;
+            }
+            // Hardcode to single hovering pointer for now.
+            std::bitset<MAX_POINTER_ID + 1> pointerIds;
+            pointerIds.set(entry.pointerProperties[0].id);
+            target->addPointers(pointerIds, touchedWindow.windowHandle->getInfo()->transform);
+            targets.push_back(*target);
         }
     }
 
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 3f2658a..017f10b 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -6592,6 +6592,29 @@
     consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
 }
 
+/**
+ * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
+ * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
+ * that the pointer is hovering over may have a different transform.
+ */
+TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
+    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
+
+    // Start hover in window 1
+    mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ADISPLAY_ID_DEFAULT, {{50, 50}}));
+    consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
+                       {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
+
+    // Move hover to window 2.
+    mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+                                                 ADISPLAY_ID_DEFAULT, {{150, 150}}));
+
+    consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
+    consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
+                       {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
+}
+
 class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
     virtual void SetUp() override {
         InputDispatcherTest::SetUp();