InputDispatcher: Only send touchpad nav gestures to trusted overlays
Because we don't want apps using the touchpad navigation gestures (at
the moment, any swipes with three or more fingers), we need to only send
them to system UI windows. For now, determine this by checking for the
TRUSTED_OVERLAY InputConfig flag.
Bug: b/279803433
Test: atest inputflinger_tests
Test: check that no events are sent to a test app when making three- or
four-finger swipes on a touchpad
Change-Id: I0830cb37d1ed615df0d6c546f1febbac89bab410
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 326ca87..0dd3dde 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 ---
@@ -2587,6 +2606,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)) {
@@ -2594,6 +2621,7 @@
// Do not send this event to those windows.
continue;
}
+
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
targets);