diff options
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 28 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 130 |
2 files changed, 157 insertions, 1 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index f3ada8e298..a3c129e31a 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -681,6 +681,25 @@ std::vector<T>& operator+=(std::vector<T>& left, const std::vector<T>& right) { return left; } +// Filter windows in a TouchState and targets in a vector to remove untrusted windows/targets from +// both. +void filterUntrustedTargets(TouchState& touchState, std::vector<InputTarget>& targets) { + std::erase_if(touchState.windows, [&](const TouchedWindow& window) { + if (!window.windowHandle->getInfo()->inputConfig.test( + WindowInfo::InputConfig::TRUSTED_OVERLAY)) { + // In addition to TouchState, erase this window from the input targets! We don't have a + // good way to do this today except by adding a nested loop. + // TODO(b/282025641): simplify this code once InputTargets are being identified + // separately from TouchedWindows. + std::erase_if(targets, [&](const InputTarget& target) { + return target.inputChannel->getConnectionToken() == window.windowHandle->getToken(); + }); + return true; + } + return false; + }); +} + } // namespace // --- InputDispatcher --- @@ -2588,6 +2607,14 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( } } + // If this is a touchpad navigation gesture, it needs to only be sent to trusted targets, as we + // only want the system UI to handle these gestures. + const bool isTouchpadNavGesture = isFromSource(entry.source, AINPUT_SOURCE_MOUSE) && + entry.classification == MotionClassification::MULTI_FINGER_SWIPE; + if (isTouchpadNavGesture) { + filterUntrustedTargets(/* byref */ tempTouchState, /* byref */ targets); + } + // Output targets from the touch state. for (const TouchedWindow& touchedWindow : tempTouchState.windows) { if (touchedWindow.pointerIds.none() && !touchedWindow.hasHoveringPointers(entry.deviceId)) { @@ -2595,6 +2622,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( // Do not send this event to those windows. continue; } + addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags, touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget, targets); diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index f6f02d8241..fecd0d1315 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -86,6 +86,8 @@ static constexpr int32_t POINTER_0_UP = AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); static constexpr int32_t POINTER_1_UP = AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); +static constexpr int32_t POINTER_2_UP = + AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); // The default pid and uid for windows created on the primary display by the test. static constexpr int32_t WINDOW_PID = 999; @@ -1660,6 +1662,11 @@ public: return *this; } + MotionArgsBuilder& classification(MotionClassification classification) { + mClassification = classification; + return *this; + } + NotifyMotionArgs build() { std::vector<PointerProperties> pointerProperties; std::vector<PointerCoords> pointerCoords; @@ -1678,7 +1685,7 @@ public: NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId, mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags, - AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0, + AMETA_NONE, mButtonState, mClassification, /*edgeFlags=*/0, mPointers.size(), pointerProperties.data(), pointerCoords.data(), /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition, mRawYCursorPosition, mDownTime, /*videoFrames=*/{}); @@ -1697,6 +1704,7 @@ private: int32_t mActionButton{0}; int32_t mButtonState{0}; int32_t mFlags{0}; + MotionClassification mClassification{MotionClassification::NONE}; float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION}; float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION}; @@ -4003,6 +4011,126 @@ TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) { EXPECT_EQ(-10, event->getY(1)); // -50 + 40 } +TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) { + std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); + sp<FakeWindowHandle> window = + sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); + window->setFrame(Rect(0, 0, 400, 400)); + sp<FakeWindowHandle> trustedOverlay = + sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay", + ADISPLAY_ID_DEFAULT); + trustedOverlay->setSpy(true); + trustedOverlay->setTrustedOverlay(true); + + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}}); + + // Start a three-finger touchpad swipe + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100)) + .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + + trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN)); + trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN)); + trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN)); + + // Move the swipe a bit + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105)) + .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + + trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); + + // End the swipe + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105)) + .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + + trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP)); + trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP)); + trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP)); + + window->assertNoEvents(); +} + +TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) { + std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); + sp<FakeWindowHandle> window = + sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); + window->setFrame(Rect(0, 0, 400, 400)); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); + + // Start a three-finger touchpad swipe + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100)) + .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + + // Move the swipe a bit + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105)) + .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + + // End the swipe + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105)) + .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105)) + .classification(MotionClassification::MULTI_FINGER_SWIPE) + .build()); + + window->assertNoEvents(); +} + /** * Ensure the correct coordinate spaces are used by InputDispatcher. * |