Loading services/inputflinger/dispatcher/InputDispatcher.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -2705,6 +2705,9 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) { continue; } if (!touchedWindow.hasTouchingPointers(entry.deviceId)) { continue; } touchedWindow.addTouchingPointers(entry.deviceId, touchingPointers); } } Loading services/inputflinger/tests/FakeWindows.h +7 −0 Original line number Diff line number Diff line Loading @@ -304,6 +304,13 @@ public: WithFlags(expectedFlags))); } inline void consumeMotionPointerDown(int32_t pointerIdx, const ::testing::Matcher<MotionEvent>& matcher) { const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher)); } inline void consumeMotionPointerUp(int32_t pointerIdx, const ::testing::Matcher<MotionEvent>& matcher) { const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP | Loading services/inputflinger/tests/InputDispatcher_test.cpp +66 −0 Original line number Diff line number Diff line Loading @@ -5357,6 +5357,72 @@ TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) { rightWindow->assertNoEvents(); } /** * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a * down event to the right window. Device B sends a down event to the left window, and then a * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the * POINTER_DOWN event should only go to the left window, and not to the right window. * This test attempts to reproduce a crash. */ TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)", ui::LogicalDisplayId::DEFAULT); leftWindow->setFrame(Rect(0, 0, 100, 100)); leftWindow->setPreventSplitting(true); sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right window", ui::LogicalDisplayId::DEFAULT); rightWindow->setFrame(Rect(100, 0, 200, 100)); mDispatcher->onWindowInfosChanged( {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0}); const DeviceId deviceA = 9; const DeviceId deviceB = 3; // Touch the right window with device A mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) .deviceId(deviceA) .build()); rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA))); // Touch the left window with device B mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .deviceId(deviceB) .build()); leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB))); // Send a second pointer from device B to the right window. It shouldn't go to the right window // because the left window prevents splitting. mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceB) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) .build()); leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB)); // Finish the gesture for both devices mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceB) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) .build()); leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB)); mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .deviceId(deviceB) .build()); leftWindow->consumeMotionEvent( AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0))); mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) .deviceId(deviceA) .build()); rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA))); } TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window", Loading services/inputflinger/tests/TestEventMatchers.h +27 −4 Original line number Diff line number Diff line Loading @@ -609,10 +609,33 @@ MATCHER_P(WithRepeatCount, repeatCount, "KeyEvent with specified repeat count") return arg.getRepeatCount() == repeatCount; } MATCHER_P2(WithPointerId, index, id, "MotionEvent with specified pointer ID for pointer index") { const auto argPointerId = arg.pointerProperties[index].id; *result_listener << "expected pointer with index " << index << " to have ID " << argPointerId; return argPointerId == id; class WithPointerIdMatcher { public: using is_gtest_matcher = void; explicit WithPointerIdMatcher(size_t index, int32_t pointerId) : mIndex(index), mPointerId(pointerId) {} bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const { return args.pointerProperties[mIndex].id == mPointerId; } bool MatchAndExplain(const MotionEvent& event, std::ostream*) const { return event.getPointerId(mIndex) == mPointerId; } void DescribeTo(std::ostream* os) const { *os << "with pointer[" << mIndex << "] id = " << mPointerId; } void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointerId"; } private: const size_t mIndex; const int32_t mPointerId; }; inline WithPointerIdMatcher WithPointerId(size_t index, int32_t pointerId) { return WithPointerIdMatcher(index, pointerId); } MATCHER_P2(WithCursorPosition, x, y, "InputEvent with specified cursor position") { Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -2705,6 +2705,9 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) { continue; } if (!touchedWindow.hasTouchingPointers(entry.deviceId)) { continue; } touchedWindow.addTouchingPointers(entry.deviceId, touchingPointers); } } Loading
services/inputflinger/tests/FakeWindows.h +7 −0 Original line number Diff line number Diff line Loading @@ -304,6 +304,13 @@ public: WithFlags(expectedFlags))); } inline void consumeMotionPointerDown(int32_t pointerIdx, const ::testing::Matcher<MotionEvent>& matcher) { const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher)); } inline void consumeMotionPointerUp(int32_t pointerIdx, const ::testing::Matcher<MotionEvent>& matcher) { const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP | Loading
services/inputflinger/tests/InputDispatcher_test.cpp +66 −0 Original line number Diff line number Diff line Loading @@ -5357,6 +5357,72 @@ TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) { rightWindow->assertNoEvents(); } /** * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a * down event to the right window. Device B sends a down event to the left window, and then a * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the * POINTER_DOWN event should only go to the left window, and not to the right window. * This test attempts to reproduce a crash. */ TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)", ui::LogicalDisplayId::DEFAULT); leftWindow->setFrame(Rect(0, 0, 100, 100)); leftWindow->setPreventSplitting(true); sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right window", ui::LogicalDisplayId::DEFAULT); rightWindow->setFrame(Rect(100, 0, 200, 100)); mDispatcher->onWindowInfosChanged( {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0}); const DeviceId deviceA = 9; const DeviceId deviceB = 3; // Touch the right window with device A mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) .deviceId(deviceA) .build()); rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA))); // Touch the left window with device B mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .deviceId(deviceB) .build()); leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB))); // Send a second pointer from device B to the right window. It shouldn't go to the right window // because the left window prevents splitting. mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceB) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) .build()); leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB)); // Finish the gesture for both devices mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN) .deviceId(deviceB) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120)) .build()); leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB)); mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) .deviceId(deviceB) .build()); leftWindow->consumeMotionEvent( AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0))); mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN) .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) .deviceId(deviceA) .build()); rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA))); } TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window", Loading
services/inputflinger/tests/TestEventMatchers.h +27 −4 Original line number Diff line number Diff line Loading @@ -609,10 +609,33 @@ MATCHER_P(WithRepeatCount, repeatCount, "KeyEvent with specified repeat count") return arg.getRepeatCount() == repeatCount; } MATCHER_P2(WithPointerId, index, id, "MotionEvent with specified pointer ID for pointer index") { const auto argPointerId = arg.pointerProperties[index].id; *result_listener << "expected pointer with index " << index << " to have ID " << argPointerId; return argPointerId == id; class WithPointerIdMatcher { public: using is_gtest_matcher = void; explicit WithPointerIdMatcher(size_t index, int32_t pointerId) : mIndex(index), mPointerId(pointerId) {} bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const { return args.pointerProperties[mIndex].id == mPointerId; } bool MatchAndExplain(const MotionEvent& event, std::ostream*) const { return event.getPointerId(mIndex) == mPointerId; } void DescribeTo(std::ostream* os) const { *os << "with pointer[" << mIndex << "] id = " << mPointerId; } void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointerId"; } private: const size_t mIndex; const int32_t mPointerId; }; inline WithPointerIdMatcher WithPointerId(size_t index, int32_t pointerId) { return WithPointerIdMatcher(index, pointerId); } MATCHER_P2(WithCursorPosition, x, y, "InputEvent with specified cursor position") { Loading