diff options
| author | 2022-11-15 03:30:48 +0000 | |
|---|---|---|
| committer | 2022-11-17 02:45:00 +0000 | |
| commit | 96483740e8dae87400b3a28e073217403363aec0 (patch) | |
| tree | d0c5dc9024a8f45c9b9d30d18db75092c8c4bc86 | |
| parent | 29bbbc408d35929203999ee431aeed48faaf0d12 (diff) | |
Fix ACTION_POINTER_DOWN reports wrong pointers
This fix the second pointer will use the identity transform because the
returned touched windows should be refreshed after updating the new
pointerIds to the temporary touch state.
Bug: 258382964
Test: atest inputflinger_tests
Change-Id: I96a738dcb01bf1c9e2792d3fee547c147dba33b5
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 25 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 37 |
2 files changed, 51 insertions, 11 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 7b7c42a211..ac08acc5c8 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2306,6 +2306,20 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked( entry.eventTime); } } + + // Update the pointerIds for non-splittable when it received pointer down. + 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); + } + } } // Update dispatching for hover enter and exit. @@ -2480,17 +2494,6 @@ Failed: } 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); - } } // Save changes unless the action was scroll in which case the temporary touch diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index aaf50ce5ed..daa3afa708 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -2400,6 +2400,43 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) { window->assertNoEvents(); } +TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) { + std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); + sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, + "Fake Window", ADISPLAY_ID_DEFAULT); + // Ensure window is non-split and have some transform. + window->setPreventSplitting(true); + window->setWindowOffset(20, 40); + mDispatcher->onWindowInfosChanged({*window->getInfo()}, {}); + + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {50, 50})) + << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; + window->consumeMotionDown(ADISPLAY_ID_DEFAULT); + + const MotionEvent secondFingerDownEvent = + MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .displayId(ADISPLAY_ID_DEFAULT) + .eventTime(systemTime(SYSTEM_TIME_MONOTONIC)) + .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50)) + .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER) + .x(-30) + .y(-50)) + .build(); + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT, + InputEventInjectionSync::WAIT_FOR_RESULT)) + << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; + + const MotionEvent* event = window->consumeMotion(); + EXPECT_EQ(POINTER_1_DOWN, event->getAction()); + EXPECT_EQ(70, event->getX(0)); // 50 + 20 + EXPECT_EQ(90, event->getY(0)); // 50 + 40 + EXPECT_EQ(-10, event->getX(1)); // -30 + 20 + EXPECT_EQ(-10, event->getY(1)); // -50 + 40 +} + /** * Ensure the correct coordinate spaces are used by InputDispatcher. * |