Loading services/inputflinger/dispatcher/InputState.cpp +12 −3 Original line number Diff line number Diff line Loading @@ -247,10 +247,19 @@ void InputState::addMotionMemento(const MotionEntry& entry, int32_t flags, bool } void InputState::MotionMemento::setPointers(const MotionEntry& entry) { pointerCount = entry.pointerCount; pointerCount = 0; for (uint32_t i = 0; i < entry.pointerCount; i++) { pointerProperties[i].copyFrom(entry.pointerProperties[i]); pointerCoords[i].copyFrom(entry.pointerCoords[i]); if (MotionEvent::getActionMasked(entry.action) == AMOTION_EVENT_ACTION_POINTER_UP) { // In POINTER_UP events, the pointer is leaving. Since the action is not stored, // this departing pointer should not be recorded. const uint8_t actionIndex = MotionEvent::getActionIndex(entry.action); if (i == actionIndex) { continue; } } pointerProperties[pointerCount].copyFrom(entry.pointerProperties[i]); pointerCoords[pointerCount].copyFrom(entry.pointerCoords[i]); pointerCount++; } } Loading services/inputflinger/tests/InputDispatcher_test.cpp +43 −1 Original line number Diff line number Diff line Loading @@ -1944,6 +1944,48 @@ TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCance wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); } /** * Two fingers down on the window, and lift off the first finger. * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event * contains a single pointer. */ TEST_F(InputDispatcherTest, CancelAfterPointer0Up) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); NotifyMotionArgs args; // First touch pointer down on right window mDispatcher->notifyMotion(&( args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100)) .build())); // Second touch pointer down mDispatcher->notifyMotion(&( args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100)) .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(110).y(100)) .build())); // First touch pointer lifts. The second one remains down mDispatcher->notifyMotion(&( args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100)) .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(110).y(100)) .build())); window->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_0_UP)); // Remove the window. The gesture should be canceled mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}}); const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}}; window->consumeMotionEvent( AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers))); } /** * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above, * with the following differences: Loading Loading @@ -2532,7 +2574,7 @@ TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) { .build())); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId), WithPointerCount(2u))); WithPointerCount(1u))); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId))); mDispatcher->notifyMotion(&( Loading Loading
services/inputflinger/dispatcher/InputState.cpp +12 −3 Original line number Diff line number Diff line Loading @@ -247,10 +247,19 @@ void InputState::addMotionMemento(const MotionEntry& entry, int32_t flags, bool } void InputState::MotionMemento::setPointers(const MotionEntry& entry) { pointerCount = entry.pointerCount; pointerCount = 0; for (uint32_t i = 0; i < entry.pointerCount; i++) { pointerProperties[i].copyFrom(entry.pointerProperties[i]); pointerCoords[i].copyFrom(entry.pointerCoords[i]); if (MotionEvent::getActionMasked(entry.action) == AMOTION_EVENT_ACTION_POINTER_UP) { // In POINTER_UP events, the pointer is leaving. Since the action is not stored, // this departing pointer should not be recorded. const uint8_t actionIndex = MotionEvent::getActionIndex(entry.action); if (i == actionIndex) { continue; } } pointerProperties[pointerCount].copyFrom(entry.pointerProperties[i]); pointerCoords[pointerCount].copyFrom(entry.pointerCoords[i]); pointerCount++; } } Loading
services/inputflinger/tests/InputDispatcher_test.cpp +43 −1 Original line number Diff line number Diff line Loading @@ -1944,6 +1944,48 @@ TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCance wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags); } /** * Two fingers down on the window, and lift off the first finger. * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event * contains a single pointer. */ TEST_F(InputDispatcherTest, CancelAfterPointer0Up) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); NotifyMotionArgs args; // First touch pointer down on right window mDispatcher->notifyMotion(&( args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100)) .build())); // Second touch pointer down mDispatcher->notifyMotion(&( args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100)) .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(110).y(100)) .build())); // First touch pointer lifts. The second one remains down mDispatcher->notifyMotion(&( args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100)) .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(110).y(100)) .build())); window->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN)); window->consumeMotionEvent(WithMotionAction(POINTER_0_UP)); // Remove the window. The gesture should be canceled mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}}); const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}}; window->consumeMotionEvent( AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers))); } /** * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above, * with the following differences: Loading Loading @@ -2532,7 +2574,7 @@ TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) { .build())); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId), WithPointerCount(2u))); WithPointerCount(1u))); window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId))); mDispatcher->notifyMotion(&( Loading