Merge "InputDispatcher: Only send touchpad nav gestures to trusted overlays" into udc-dev am: 89b675ef28 am: 78afcb7f2d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/23114716
Change-Id: Id38d352f74f2316190e211cb55741a2f0ed8346f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index f3ada8e..a3c129e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -681,6 +681,25 @@
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 @@
}
}
+ // 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 @@
// 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 f6f02d8..fecd0d1 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -86,6 +86,8 @@
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 @@
return *this;
}
+ MotionArgsBuilder& classification(MotionClassification classification) {
+ mClassification = classification;
+ return *this;
+ }
+
NotifyMotionArgs build() {
std::vector<PointerProperties> pointerProperties;
std::vector<PointerCoords> pointerCoords;
@@ -1678,7 +1685,7 @@
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 @@
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 @@
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.
*