Update mKeyIsWaitingForEventsTimeout separately from the prune check
Before this CL, the variable mKeyIsWaitingForEventsTimeout was getting
updated inside 'shouldPruneInboundQueueLocked', but that is not the
correct place to do this update. In this CL, we move this update to the
enqueue function, and this allows us to make
'shouldPruneInboundQueueLocked' const.
The current behaviour of:
```
When there are unprocessed motion events, we wait up to 500 ms to send
any key events, in anticipation that focus might change. However, if
there are subsequent "ACTION_DOWN" events, we don't want to be adding
this 500ms wait, so we short-circuit the timeout and process the pending
keys immediately (send them to the currently focused window).
```
is not changed in this CL.
However, we are updating the test for this behaviour to:
- Be correctly named. The pending key is not dropped, but it's processed
immediately instead.
- Actually test the behaviour in question. Previously, the test passed
even with the 'mKeyIsWaitingForEventsTimeout' not getting updated
during the queueing stage. This is because the test used a large
(1000ms) timeout for event consumption. So in practice, the test was
still waiting for 500 ms and only then the consumption passed.
In this CL, the test is changed so that it consumes within the allotted
timeframe. If this becomes problematic (flaky), we would need to change
the KEY_WAITING_FOR_EVENTS_TIMEOUT and possibly provide that value from
the policy, thus allowing the test to override it. Or, another way to
fix flakes here would be to switch to an injectable clock, although in
that case we would still ideally open up KEY_WAITING_FOR_EVENTS_TIMEOUT
for tests, or maybe just hardcode the value with a comment, similarly to
how it's currently done.
Bug: 294553757
Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST
Change-Id: Ife71634960b365df1d106fd28f0dc0047ac2ed2b
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index af72eb9..77c2222 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -121,11 +121,6 @@
// Log a warning when an interception call takes longer than this to process.
constexpr std::chrono::milliseconds SLOW_INTERCEPTION_THRESHOLD = 50ms;
-// Additional key latency in case a connection is still processing some motion events.
-// This will help with the case when a user touched a button that opens a new window,
-// and gives us the chance to dispatch the key to this new window.
-constexpr std::chrono::nanoseconds KEY_WAITING_FOR_EVENTS_TIMEOUT = 500ms;
-
// Number of recent events to keep for debugging purposes.
constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
@@ -1192,7 +1187,7 @@
* Return true if the events preceding this incoming motion event should be dropped
* Return false otherwise (the default behaviour)
*/
-bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) {
+bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) const {
const bool isPointerDownEvent = motionEntry.action == AMOTION_EVENT_ACTION_DOWN &&
isFromSource(motionEntry.source, AINPUT_SOURCE_CLASS_POINTER);
@@ -1234,16 +1229,6 @@
}
}
- // Prevent getting stuck: if we have a pending key event, and some motion events that have not
- // yet been processed by some connections, the dispatcher will wait for these motion
- // events to be processed before dispatching the key event. This is because these motion events
- // may cause a new window to be launched, which the user might expect to receive focus.
- // To prevent waiting forever for such events, just send the key to the currently focused window
- if (isPointerDownEvent && mKeyIsWaitingForEventsTimeout) {
- ALOGD("Received a new pointer down event, stop waiting for events to process and "
- "just send the pending key event to the focused window.");
- mKeyIsWaitingForEventsTimeout = now();
- }
return false;
}
@@ -1291,6 +1276,20 @@
mNextUnblockedEvent = mInboundQueue.back();
needWake = true;
}
+
+ const bool isPointerDownEvent = motionEntry.action == AMOTION_EVENT_ACTION_DOWN &&
+ isFromSource(motionEntry.source, AINPUT_SOURCE_CLASS_POINTER);
+ if (isPointerDownEvent && mKeyIsWaitingForEventsTimeout) {
+ // Prevent waiting too long for unprocessed events: if we have a pending key event,
+ // and some other events have not yet been processed, the dispatcher will wait for
+ // these events to be processed before dispatching the key event. This is because
+ // the unprocessed events may cause the focus to change (for example, by launching a
+ // new window or tapping a different window). To prevent waiting too long, we force
+ // the key to be sent to the currently focused window when a new tap comes in.
+ ALOGD("Received a new pointer down event, stop waiting for events to process and "
+ "just send the pending key event to the currently focused window.");
+ mKeyIsWaitingForEventsTimeout = now();
+ }
break;
}
case EventEntry::Type::FOCUS: {
@@ -2137,7 +2136,8 @@
// Start the timer
// Wait to send key because there are unprocessed events that may cause focus to change
mKeyIsWaitingForEventsTimeout = currentTime +
- std::chrono::duration_cast<std::chrono::nanoseconds>(KEY_WAITING_FOR_EVENTS_TIMEOUT)
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ mPolicy.getKeyWaitingForEventsTimeout())
.count();
return true;
}
@@ -4879,7 +4879,7 @@
break;
}
default: {
- ALOGE("Cannot verify events of type %" PRId32, event.getType());
+ LOG(ERROR) << "Cannot verify events of type " << ftl::enum_string(event.getType());
return nullptr;
}
}