Merge "Fix broken Drag and Drop" into main
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 54da8e8..6ad3de0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3980,16 +3980,6 @@
void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
const std::shared_ptr<Connection>& connection, const CancelationOptions& options) {
- if ((options.mode == CancelationOptions::Mode::CANCEL_POINTER_EVENTS ||
- options.mode == CancelationOptions::Mode::CANCEL_ALL_EVENTS) &&
- mDragState && mDragState->dragWindow->getToken() == connection->inputChannel->getToken()) {
- LOG(INFO) << __func__
- << ": Canceling drag and drop because the pointers for the drag window are being "
- "canceled.";
- sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0);
- mDragState.reset();
- }
-
if (connection->status == Connection::Status::BROKEN) {
return;
}
@@ -4002,6 +3992,7 @@
if (cancelationEvents.empty()) {
return;
}
+
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
"with reality: %s, mode=%s.",
@@ -4050,6 +4041,14 @@
pointerIndex++) {
pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
}
+ if (mDragState && mDragState->dragWindow->getToken() == token &&
+ pointerIds.test(mDragState->pointerId)) {
+ LOG(INFO) << __func__
+ << ": Canceling drag and drop because the pointers for the drag "
+ "window are being canceled.";
+ sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0);
+ mDragState.reset();
+ }
addPointerWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS,
pointerIds, motionEntry.downTime, targets);
} else {
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 29fdec7..e220133 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -9660,6 +9660,50 @@
mSecondWindow->assertNoEvents();
}
+TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
+ startDrag();
+
+ // No cancel event after drag start
+ mSpyWindow->assertNoEvents();
+
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
+ .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ // Receives cancel for first pointer after next pointer down
+ mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
+ mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+ mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+
+ mSpyWindow->assertNoEvents();
+
+ // Spy window calls pilfer pointers
+ EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
+ mDragWindow->assertNoEvents();
+
+ const MotionEvent firstFingerMoveEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
+ .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ // Drag window should still receive the new event
+ mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+ mDragWindow->assertNoEvents();
+}
+
TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
startDrag(true, AINPUT_SOURCE_STYLUS);