summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Prabir Pradhan <prabirmsp@google.com> 2023-11-02 18:05:36 +0000
committer Prabir Pradhan <prabirmsp@google.com> 2023-11-03 21:54:00 +0000
commitb9dd164bea3b6855517ac1b17fd02a68aa297c90 (patch)
tree8c0a0b4f78867e123042ede13c8c9f498b08bc1b
parenta8cdbe17cded8d5747fccdf43552fdcef8392526 (diff)
Do not re-use the same EventEntry and DispatchEntry for fallback keys
Re-using the same EventEntry and DispatchEntry for fallbacks is incorrect. A fallback can be thought of as a completely new event generated for a channel, in which case it should not share the same eventId as the original event. Re-using the same DispatchEntry leads to the incorrect behavior, since the expected flags in the event will be overridden by the the resolvedFlags (and other resolved fields) from the old DispatchEntry. This CL also fixed this incorrect behavior, which is verified with the new tests added in the following CL. Bug: 210460522 Test: atest inputflinger_tests Change-Id: I30fd72a7da85043ea19fedaace41e79b20c85645
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp66
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.h10
2 files changed, 30 insertions, 46 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 219b5670f9..c8528e1a03 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -6169,7 +6169,7 @@ void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
uint32_t seq, bool handled,
nsecs_t consumeTime) {
// Handle post-event policy actions.
- bool restartEvent;
+ std::unique_ptr<KeyEntry> fallbackKeyEntry;
{ // Start critical section
auto dispatchEntryIt =
@@ -6193,15 +6193,9 @@ void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
}
if (dispatchEntry.eventEntry->type == EventEntry::Type::KEY) {
- KeyEntry& keyEntry = static_cast<KeyEntry&>(*(dispatchEntry.eventEntry));
- restartEvent =
+ const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*(dispatchEntry.eventEntry));
+ fallbackKeyEntry =
afterKeyEventLockedInterruptable(connection, dispatchEntry, keyEntry, handled);
- } else if (dispatchEntry.eventEntry->type == EventEntry::Type::MOTION) {
- MotionEntry& motionEntry = static_cast<MotionEntry&>(*(dispatchEntry.eventEntry));
- restartEvent = afterMotionEventLockedInterruptable(connection, dispatchEntry,
- motionEntry, handled);
- } else {
- restartEvent = false;
}
} // End critical section: The -LockedInterruptable methods may have released the lock.
@@ -6225,12 +6219,13 @@ void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
}
}
traceWaitQueueLength(*connection);
- if (restartEvent && connection->status == Connection::Status::NORMAL) {
- connection->outboundQueue.emplace_front(std::move(dispatchEntry));
- traceOutboundQueueLength(*connection);
- } else {
- releaseDispatchEntry(std::move(dispatchEntry));
+ if (fallbackKeyEntry && connection->status == Connection::Status::NORMAL) {
+ const InputTarget target{.inputChannel = connection->inputChannel,
+ .flags = dispatchEntry->targetFlags};
+ enqueueDispatchEntryLocked(connection, std::move(fallbackKeyEntry), target,
+ InputTarget::Flags::DISPATCH_AS_IS);
}
+ releaseDispatchEntry(std::move(dispatchEntry));
}
// Start the next dispatch cycle for this connection.
@@ -6415,15 +6410,15 @@ void InputDispatcher::processConnectionResponsiveLocked(const Connection& connec
sendWindowResponsiveCommandLocked(connectionToken, pid);
}
-bool InputDispatcher::afterKeyEventLockedInterruptable(
+std::unique_ptr<KeyEntry> InputDispatcher::afterKeyEventLockedInterruptable(
const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
- KeyEntry& keyEntry, bool handled) {
+ const KeyEntry& keyEntry, bool handled) {
if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) {
if (!handled) {
// Report the key as unhandled, since the fallback was not handled.
mReporter->reportUnhandledKey(keyEntry.id);
}
- return false;
+ return {};
}
// Get the fallback key state.
@@ -6483,7 +6478,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(
"keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
originalKeyCode, keyEntry.action, keyEntry.repeatCount, keyEntry.policyFlags);
}
- return false;
+ return {};
}
// Dispatch the unhandled key to the policy.
@@ -6508,7 +6503,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(
if (connection->status != Connection::Status::NORMAL) {
connection->inputState.removeFallbackKey(originalKeyCode);
- return false;
+ return {};
}
// Latch the fallback keycode for this key on an initial down.
@@ -6569,25 +6564,22 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(
}
if (fallback) {
- // Restart the dispatch cycle using the fallback key.
- keyEntry.eventTime = event.getEventTime();
- keyEntry.deviceId = event.getDeviceId();
- keyEntry.source = event.getSource();
- keyEntry.displayId = event.getDisplayId();
- keyEntry.flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
- keyEntry.keyCode = *fallbackKeyCode;
- keyEntry.scanCode = event.getScanCode();
- keyEntry.metaState = event.getMetaState();
- keyEntry.repeatCount = event.getRepeatCount();
- keyEntry.downTime = event.getDownTime();
- keyEntry.syntheticRepeat = false;
-
+ // Return the fallback key that we want dispatched to the channel.
+ std::unique_ptr<KeyEntry> newEntry =
+ std::make_unique<KeyEntry>(mIdGenerator.nextId(), keyEntry.injectionState,
+ event.getEventTime(), event.getDeviceId(),
+ event.getSource(), event.getDisplayId(),
+ keyEntry.policyFlags, keyEntry.action,
+ event.getFlags() | AKEY_EVENT_FLAG_FALLBACK,
+ *fallbackKeyCode, event.getScanCode(),
+ event.getMetaState(), event.getRepeatCount(),
+ event.getDownTime());
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
ALOGD("Unhandled key event: Dispatching fallback key. "
"originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
originalKeyCode, *fallbackKeyCode, keyEntry.metaState);
}
- return true; // restart the event
+ return newEntry;
} else {
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
ALOGD("Unhandled key event: No fallback key.");
@@ -6597,13 +6589,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(
mReporter->reportUnhandledKey(keyEntry.id);
}
}
- return false;
-}
-
-bool InputDispatcher::afterMotionEventLockedInterruptable(
- const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
- MotionEntry& motionEntry, bool handled) {
- return false;
+ return {};
}
void InputDispatcher::traceInboundQueueLengthLocked() {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index e428c4e915..f0f67721e7 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -660,12 +660,10 @@ private:
void updateLastAnrStateLocked(const std::string& windowLabel, const std::string& reason)
REQUIRES(mLock);
std::map<int32_t /*displayId*/, InputVerifier> mVerifiersByDisplay;
- bool afterKeyEventLockedInterruptable(const std::shared_ptr<Connection>& connection,
- DispatchEntry& dispatchEntry, KeyEntry& keyEntry,
- bool handled) REQUIRES(mLock);
- bool afterMotionEventLockedInterruptable(const std::shared_ptr<Connection>& connection,
- DispatchEntry& dispatchEntry, MotionEntry& motionEntry,
- bool handled) REQUIRES(mLock);
+ // Returns a fallback KeyEntry that should be sent to the connection, if required.
+ std::unique_ptr<KeyEntry> afterKeyEventLockedInterruptable(
+ const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
+ const KeyEntry& keyEntry, bool handled) REQUIRES(mLock);
// Find touched state and touched window by token.
std::tuple<TouchState*, TouchedWindow*, int32_t /*displayId*/>