Loading services/inputflinger/dispatcher/InputDispatcher.cpp +28 −27 Original line number Diff line number Diff line Loading @@ -2195,10 +2195,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( // Update the temporary touch state. BitSet32 pointerIds; if (isSplit) { uint32_t pointerId = entry.pointerProperties[pointerIndex].id; pointerIds.markBit(pointerId); } pointerIds.markBit(entry.pointerProperties[pointerIndex].id); tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds); } Loading Loading @@ -2275,9 +2272,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } BitSet32 pointerIds; if (isSplit) { pointerIds.markBit(entry.pointerProperties[0].id); } tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds); } } Loading Loading @@ -2453,21 +2448,28 @@ Failed: } } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { // One pointer went up. if (isSplit) { int32_t pointerIndex = getMotionEventActionPointerIndex(action); uint32_t pointerId = entry.pointerProperties[pointerIndex].id; for (size_t i = 0; i < tempTouchState.windows.size();) { TouchedWindow& touchedWindow = tempTouchState.windows[i]; if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) { touchedWindow.pointerIds.clearBit(pointerId); if (touchedWindow.pointerIds.isEmpty()) { tempTouchState.windows.erase(tempTouchState.windows.begin() + i); continue; } } i += 1; } } else if (!isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) { // If no split, we suppose all touched windows should receive pointer down. const int32_t pointerIndex = getMotionEventActionPointerIndex(action); for (size_t i = 0; i < tempTouchState.windows.size(); i++) { TouchedWindow& touchedWindow = tempTouchState.windows[i]; // Ignore drag window for it should just track one pointer. if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) { continue; } touchedWindow.pointerIds.markBit(entry.pointerProperties[pointerIndex].id); } } Loading Loading @@ -5087,14 +5089,13 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< // Store the dragging window. if (isDragDrop) { if (pointerIds.count() > 1) { ALOGW("The drag and drop cannot be started when there is more than 1 pointer on the" " window."); if (pointerIds.count() != 1) { ALOGW("The drag and drop cannot be started when there is no pointer or more than 1" " pointer on the window."); return false; } // If the window didn't not support split or the source is mouse, the pointerIds count // would be 0, so we have to track the pointer 0. const int32_t id = pointerIds.count() == 0 ? 0 : pointerIds.firstMarkedBit(); // Track the pointer id for drag window and generate the drag state. const int32_t id = pointerIds.firstMarkedBit(); mDragState = std::make_unique<DragState>(toWindowHandle, id); } Loading services/inputflinger/dispatcher/InputTarget.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -43,8 +43,8 @@ std::string dispatchModeToString(int32_t dispatchMode) { } void InputTarget::addPointers(BitSet32 newPointerIds, const ui::Transform& transform) { // The pointerIds can be empty, but still a valid InputTarget. This can happen for Monitors // and non splittable windows since we will just use all the pointers from the input event. // The pointerIds can be empty, but still a valid InputTarget. This can happen when there is no // valid pointer property from the input event. if (newPointerIds.isEmpty()) { setDefaultPointerTransform(transform); return; Loading services/inputflinger/dispatcher/TouchedWindow.h +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ namespace inputdispatcher { struct TouchedWindow { sp<gui::WindowInfoHandle> windowHandle; int32_t targetFlags; BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set BitSet32 pointerIds; }; } // namespace inputdispatcher Loading services/inputflinger/tests/InputDispatcher_test.cpp +98 −40 Original line number Diff line number Diff line Loading @@ -6125,6 +6125,8 @@ protected: sp<FakeWindowHandle> mWindow; sp<FakeWindowHandle> mSecondWindow; sp<FakeWindowHandle> mDragWindow; // Mouse would force no-split, set the id as non-zero to verify if drag state could track it. static constexpr int32_t MOUSE_POINTER_ID = 1; void SetUp() override { InputDispatcherTest::SetUp(); Loading @@ -6139,11 +6141,41 @@ protected: mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}}); } void injectDown() { void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) { switch (fromSource) { case AINPUT_SOURCE_TOUCHSCREEN: ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50})) injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; break; case AINPUT_SOURCE_STYLUS: ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent( mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS) .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS) .x(50) .y(50)) .build())); break; case AINPUT_SOURCE_MOUSE: ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent( mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE) .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) .pointer(PointerBuilder(MOUSE_POINTER_ID, AMOTION_EVENT_TOOL_TYPE_MOUSE) .x(50) .y(50)) .build())); break; default: FAIL() << "Source " << fromSource << " doesn't support drag and drop"; } // Window should receive motion event. mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); Loading @@ -6152,9 +6184,9 @@ protected: // Start performing drag, we will create a drag window and transfer touch to it. // @param sendDown : if true, send a motion down on first window before perform drag and drop. // Returns true on success. bool performDrag(bool sendDown = true) { bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) { if (sendDown) { injectDown(); injectDown(fromSource); } // The drag window covers the entire display Loading @@ -6172,36 +6204,10 @@ protected: } return transferred; } // Start performing drag, we will create a drag window and transfer touch to it. void performStylusDrag() { ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS) .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS) .x(50) .y(50)) .build())); mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); // The drag window covers the entire display mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT); mDispatcher->setInputWindows( {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}}); // Transfer touch focus to the drag window mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(), true /* isDragDrop */); mWindow->consumeMotionCancel(); mDragWindow->consumeMotionDown(); } }; TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) { performDrag(); startDrag(); // Move on window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, Loading Loading @@ -6239,7 +6245,7 @@ TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) { } TEST_F(InputDispatcherDragTests, DragAndDrop) { performDrag(); startDrag(); // Move on window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, Loading Loading @@ -6271,7 +6277,7 @@ TEST_F(InputDispatcherDragTests, DragAndDrop) { } TEST_F(InputDispatcherDragTests, StylusDragAndDrop) { performStylusDrag(); startDrag(true, AINPUT_SOURCE_STYLUS); // Move on window and keep button pressed. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, Loading Loading @@ -6318,7 +6324,7 @@ TEST_F(InputDispatcherDragTests, StylusDragAndDrop) { } TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) { performDrag(); startDrag(); // Set second window invisible. mSecondWindow->setVisible(false); Loading Loading @@ -6354,6 +6360,9 @@ TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) { } TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) { // Ensure window could track pointerIds if it didn't support split touch. mWindow->setPreventSplitting(true); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50})) Loading @@ -6374,7 +6383,7 @@ TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) { mWindow->consumeMotionPointerDown(1 /* pointerIndex */); // Should not perform drag and drop when window has multi fingers. ASSERT_FALSE(performDrag(false)); ASSERT_FALSE(startDrag(false)); } TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { Loading Loading @@ -6402,7 +6411,7 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); // Perform drag and drop from first window. ASSERT_TRUE(performDrag(false)); ASSERT_TRUE(startDrag(false)); // Move on window. const MotionEvent secondFingerMoveEvent = Loading Loading @@ -6437,7 +6446,7 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { } TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { performDrag(); startDrag(); // Update window of second display. sp<FakeWindowHandle> windowInSecondary = Loading Loading @@ -6488,6 +6497,55 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { mSecondWindow->assertNoEvents(); } TEST_F(InputDispatcherDragTests, MouseDragAndDrop) { startDrag(true, AINPUT_SOURCE_MOUSE); // Move on window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE) .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) .pointer(PointerBuilder(MOUSE_POINTER_ID, AMOTION_EVENT_TOOL_TYPE_MOUSE) .x(50) .y(50)) .build())) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); mWindow->consumeDragEvent(false, 50, 50); mSecondWindow->assertNoEvents(); // Move to another window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE) .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) .pointer(PointerBuilder(MOUSE_POINTER_ID, AMOTION_EVENT_TOOL_TYPE_MOUSE) .x(150) .y(50)) .build())) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); mWindow->consumeDragEvent(true, 150, 50); mSecondWindow->consumeDragEvent(false, 50, 50); // drop to another window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE) .buttonState(0) .pointer(PointerBuilder(MOUSE_POINTER_ID, AMOTION_EVENT_TOOL_TYPE_MOUSE) .x(150) .y(50)) .build())) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken()); mWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); } class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +28 −27 Original line number Diff line number Diff line Loading @@ -2195,10 +2195,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( // Update the temporary touch state. BitSet32 pointerIds; if (isSplit) { uint32_t pointerId = entry.pointerProperties[pointerIndex].id; pointerIds.markBit(pointerId); } pointerIds.markBit(entry.pointerProperties[pointerIndex].id); tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds); } Loading Loading @@ -2275,9 +2272,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked( } BitSet32 pointerIds; if (isSplit) { pointerIds.markBit(entry.pointerProperties[0].id); } tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds); } } Loading Loading @@ -2453,21 +2448,28 @@ Failed: } } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { // One pointer went up. if (isSplit) { int32_t pointerIndex = getMotionEventActionPointerIndex(action); uint32_t pointerId = entry.pointerProperties[pointerIndex].id; for (size_t i = 0; i < tempTouchState.windows.size();) { TouchedWindow& touchedWindow = tempTouchState.windows[i]; if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) { touchedWindow.pointerIds.clearBit(pointerId); if (touchedWindow.pointerIds.isEmpty()) { tempTouchState.windows.erase(tempTouchState.windows.begin() + i); continue; } } i += 1; } } else if (!isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) { // If no split, we suppose all touched windows should receive pointer down. const int32_t pointerIndex = getMotionEventActionPointerIndex(action); for (size_t i = 0; i < tempTouchState.windows.size(); i++) { TouchedWindow& touchedWindow = tempTouchState.windows[i]; // Ignore drag window for it should just track one pointer. if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) { continue; } touchedWindow.pointerIds.markBit(entry.pointerProperties[pointerIndex].id); } } Loading Loading @@ -5087,14 +5089,13 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp< // Store the dragging window. if (isDragDrop) { if (pointerIds.count() > 1) { ALOGW("The drag and drop cannot be started when there is more than 1 pointer on the" " window."); if (pointerIds.count() != 1) { ALOGW("The drag and drop cannot be started when there is no pointer or more than 1" " pointer on the window."); return false; } // If the window didn't not support split or the source is mouse, the pointerIds count // would be 0, so we have to track the pointer 0. const int32_t id = pointerIds.count() == 0 ? 0 : pointerIds.firstMarkedBit(); // Track the pointer id for drag window and generate the drag state. const int32_t id = pointerIds.firstMarkedBit(); mDragState = std::make_unique<DragState>(toWindowHandle, id); } Loading
services/inputflinger/dispatcher/InputTarget.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -43,8 +43,8 @@ std::string dispatchModeToString(int32_t dispatchMode) { } void InputTarget::addPointers(BitSet32 newPointerIds, const ui::Transform& transform) { // The pointerIds can be empty, but still a valid InputTarget. This can happen for Monitors // and non splittable windows since we will just use all the pointers from the input event. // The pointerIds can be empty, but still a valid InputTarget. This can happen when there is no // valid pointer property from the input event. if (newPointerIds.isEmpty()) { setDefaultPointerTransform(transform); return; Loading
services/inputflinger/dispatcher/TouchedWindow.h +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ namespace inputdispatcher { struct TouchedWindow { sp<gui::WindowInfoHandle> windowHandle; int32_t targetFlags; BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set BitSet32 pointerIds; }; } // namespace inputdispatcher Loading
services/inputflinger/tests/InputDispatcher_test.cpp +98 −40 Original line number Diff line number Diff line Loading @@ -6125,6 +6125,8 @@ protected: sp<FakeWindowHandle> mWindow; sp<FakeWindowHandle> mSecondWindow; sp<FakeWindowHandle> mDragWindow; // Mouse would force no-split, set the id as non-zero to verify if drag state could track it. static constexpr int32_t MOUSE_POINTER_ID = 1; void SetUp() override { InputDispatcherTest::SetUp(); Loading @@ -6139,11 +6141,41 @@ protected: mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}}); } void injectDown() { void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) { switch (fromSource) { case AINPUT_SOURCE_TOUCHSCREEN: ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50})) injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50})) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; break; case AINPUT_SOURCE_STYLUS: ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent( mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS) .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS) .x(50) .y(50)) .build())); break; case AINPUT_SOURCE_MOUSE: ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent( mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE) .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) .pointer(PointerBuilder(MOUSE_POINTER_ID, AMOTION_EVENT_TOOL_TYPE_MOUSE) .x(50) .y(50)) .build())); break; default: FAIL() << "Source " << fromSource << " doesn't support drag and drop"; } // Window should receive motion event. mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); Loading @@ -6152,9 +6184,9 @@ protected: // Start performing drag, we will create a drag window and transfer touch to it. // @param sendDown : if true, send a motion down on first window before perform drag and drop. // Returns true on success. bool performDrag(bool sendDown = true) { bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) { if (sendDown) { injectDown(); injectDown(fromSource); } // The drag window covers the entire display Loading @@ -6172,36 +6204,10 @@ protected: } return transferred; } // Start performing drag, we will create a drag window and transfer touch to it. void performStylusDrag() { ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS) .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS) .x(50) .y(50)) .build())); mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); // The drag window covers the entire display mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT); mDispatcher->setInputWindows( {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}}); // Transfer touch focus to the drag window mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(), true /* isDragDrop */); mWindow->consumeMotionCancel(); mDragWindow->consumeMotionDown(); } }; TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) { performDrag(); startDrag(); // Move on window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, Loading Loading @@ -6239,7 +6245,7 @@ TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) { } TEST_F(InputDispatcherDragTests, DragAndDrop) { performDrag(); startDrag(); // Move on window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, Loading Loading @@ -6271,7 +6277,7 @@ TEST_F(InputDispatcherDragTests, DragAndDrop) { } TEST_F(InputDispatcherDragTests, StylusDragAndDrop) { performStylusDrag(); startDrag(true, AINPUT_SOURCE_STYLUS); // Move on window and keep button pressed. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, Loading Loading @@ -6318,7 +6324,7 @@ TEST_F(InputDispatcherDragTests, StylusDragAndDrop) { } TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) { performDrag(); startDrag(); // Set second window invisible. mSecondWindow->setVisible(false); Loading Loading @@ -6354,6 +6360,9 @@ TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) { } TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) { // Ensure window could track pointerIds if it didn't support split touch. mWindow->setPreventSplitting(true); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50})) Loading @@ -6374,7 +6383,7 @@ TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) { mWindow->consumeMotionPointerDown(1 /* pointerIndex */); // Should not perform drag and drop when window has multi fingers. ASSERT_FALSE(performDrag(false)); ASSERT_FALSE(startDrag(false)); } TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { Loading Loading @@ -6402,7 +6411,7 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); // Perform drag and drop from first window. ASSERT_TRUE(performDrag(false)); ASSERT_TRUE(startDrag(false)); // Move on window. const MotionEvent secondFingerMoveEvent = Loading Loading @@ -6437,7 +6446,7 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { } TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { performDrag(); startDrag(); // Update window of second display. sp<FakeWindowHandle> windowInSecondary = Loading Loading @@ -6488,6 +6497,55 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { mSecondWindow->assertNoEvents(); } TEST_F(InputDispatcherDragTests, MouseDragAndDrop) { startDrag(true, AINPUT_SOURCE_MOUSE); // Move on window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE) .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) .pointer(PointerBuilder(MOUSE_POINTER_ID, AMOTION_EVENT_TOOL_TYPE_MOUSE) .x(50) .y(50)) .build())) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); mWindow->consumeDragEvent(false, 50, 50); mSecondWindow->assertNoEvents(); // Move to another window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE) .buttonState(AMOTION_EVENT_BUTTON_PRIMARY) .pointer(PointerBuilder(MOUSE_POINTER_ID, AMOTION_EVENT_TOOL_TYPE_MOUSE) .x(150) .y(50)) .build())) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); mWindow->consumeDragEvent(true, 150, 50); mSecondWindow->consumeDragEvent(false, 50, 50); // drop to another window. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE) .buttonState(0) .pointer(PointerBuilder(MOUSE_POINTER_ID, AMOTION_EVENT_TOOL_TYPE_MOUSE) .x(150) .y(50)) .build())) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken()); mWindow->assertNoEvents(); mSecondWindow->assertNoEvents(); } class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { Loading