Only send events to windows with pointers
Due to the recent refactor, some of the windows with only hovering
pointers are getting persisted inside TouchState. This is the case for
the hovering pointers from mouse, for example. Mouse usually never
leaves the screen, so it's always inside some window.
However, we are still currently iterating over TouchedWindows inside
the TouchState in order to determine which targets should receive the
current entry.
That means that the windows that are hovered over will always be there,
which is not something that we want. It would cause the events to go
to windows that are not directly getting touched.
To avoid this, make sure that the pointers are indeed supposed to be
going to the current window. In a future refactor, we will store the pointers
per-device, as well.
The added test reproduces a condition where we crash due to mismatching
downtimes.
There are few issues that it exposes.
1) We currently use hover events for setting the downtime of a window,
which we shouldn't do.
2) If a window is not receiving the events from the current device, it
shouldn't be in the dispatching list. So we should not be sending the
events there to begin with.
Bug: 266455987
Test: m inputflinger_tests && $ANDROID_HOST_OUT/nativetest64/inputflinger_tests/inputflinger_tests --gtest_filter="*HoverFromLeftToRightAndTap*"
Change-Id: Ic0d2a1ed6d053e18077bc7216b1ce02e88017b4a
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 0f3dc5c..44c133c 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2303,8 +2303,13 @@
pointerIds.markBit(entry.pointerProperties[pointerIndex].id);
}
+ const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN ||
+ maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN;
+
tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds,
- entry.eventTime);
+ isDownOrPointerDown
+ ? std::make_optional(entry.eventTime)
+ : std::nullopt);
// If this is the pointer going down and the touched window has a wallpaper
// then also add the touched wallpaper windows so they are locked in for the duration
@@ -2312,8 +2317,7 @@
// We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
// engine only supports touch events. We would need to add a mechanism similar
// to View.onGenericMotionEvent to enable wallpapers to handle these events.
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
- maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
+ if (isDownOrPointerDown) {
if (targetFlags.test(InputTarget::Flags::FOREGROUND) &&
windowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
@@ -2517,6 +2521,12 @@
// Success! Output targets from the touch state.
tempTouchState.clearWindowsWithoutPointers();
for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
+ if (touchedWindow.pointerIds.isEmpty() &&
+ !touchedWindow.hasHoveringPointers(entry.deviceId)) {
+ // Windows with hovering pointers are getting persisted inside TouchState.
+ // Do not send this event to those windows.
+ continue;
+ }
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
targets);