InputDispatcher: Establish 1:1 relation between eventId and EventEntry

Previously, one event could be dispatched as events with different
actions and flags to different windows. For example, a HOVER_MOVE
event can technically be dispatched as HOVER_ENTER, HOVER_MOVE, or
HOVER_EXIT. We achieved this by "overriding" the action and flags
in the EventEntry using the DispatchEntry. This was further complicated
by the fact that we wanted to generate a new eventId in some cases
and not in others.

To simplify this logic, we will establish a 1:1 relationship between
eventId and EventEntry, so that eventIds will never be overridden
during dispatch. We will also simplify things further by using a new
eventId (therefore also creating a new EventEntry) whenever the action
of an event is to change. There will no longer be an action override
in DispatchEntry either.

Even after this change, there are still fields that will need to be
modified for each DispatchEntry, namely the flags and coordinates
that take the window/display transforms into account, so this change
is not intended to create a 1:1 relation between eventId and outbound
events from InputDispatcher.

Bug: 210460522
Test: atest inputflinger_tests
Change-Id: I158267081814d856d7fedf05c02c284717533d6c
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 3f3fd00..4a2c944 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -295,9 +295,8 @@
         }
         dump.append(INDENT4);
         dump += entry.eventEntry->getDescription();
-        dump += StringPrintf(", seq=%" PRIu32 ", targetFlags=%s, resolvedAction=%d, age=%" PRId64
-                             "ms",
-                             entry.seq, entry.targetFlags.string().c_str(), entry.resolvedAction,
+        dump += StringPrintf(", seq=%" PRIu32 ", targetFlags=%s, age=%" PRId64 "ms", entry.seq,
+                             entry.targetFlags.string().c_str(),
                              ns2ms(currentTime - entry.eventEntry->eventTime));
         if (entry.deliveryTime != 0) {
             // This entry was delivered, so add information on how long we've been waiting
@@ -455,10 +454,6 @@
 bool shouldReportFinishedEvent(const DispatchEntry& dispatchEntry, const Connection& connection) {
     const EventEntry& eventEntry = *dispatchEntry.eventEntry;
     const int32_t& inputEventId = eventEntry.id;
-    if (inputEventId != dispatchEntry.resolvedEventId) {
-        // Event was transmuted
-        return false;
-    }
     if (inputEventId == android::os::IInputConstants::INVALID_INPUT_EVENT_ID) {
         return false;
     }
@@ -3333,13 +3328,12 @@
 
     // Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
     // different EventEntry than what was passed in.
-    const EventEntry& newEntry = *(dispatchEntry->eventEntry);
+    eventEntry = dispatchEntry->eventEntry;
     // Apply target flags and update the connection's input state.
-    switch (newEntry.type) {
+    switch (eventEntry->type) {
         case EventEntry::Type::KEY: {
-            const KeyEntry& keyEntry = static_cast<const KeyEntry&>(newEntry);
-            if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
-                                                 dispatchEntry->resolvedFlags)) {
+            const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*eventEntry);
+            if (!connection->inputState.trackKey(keyEntry, keyEntry.flags)) {
                 LOG(WARNING) << "channel " << connection->getInputChannelName()
                              << "~ dropping inconsistent event: " << *dispatchEntry;
                 return; // skip the inconsistent event
@@ -3348,58 +3342,90 @@
         }
 
         case EventEntry::Type::MOTION: {
-            const MotionEntry& motionEntry = static_cast<const MotionEntry&>(newEntry);
-            // Assign a default value to dispatchEntry that will never be generated by InputReader,
-            // and assign a InputDispatcher value if it doesn't change in the if-else chain below.
-            constexpr int32_t DEFAULT_RESOLVED_EVENT_ID =
-                    static_cast<int32_t>(IdGenerator::Source::OTHER);
-            dispatchEntry->resolvedEventId = DEFAULT_RESOLVED_EVENT_ID;
-            if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
-            } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
-            } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_ENTER)) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
-            } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
-            } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
-            } else {
-                dispatchEntry->resolvedEventId = motionEntry.id;
-            }
-            if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
-                !connection->inputState.isHovering(motionEntry.deviceId, motionEntry.source,
-                                                   motionEntry.displayId)) {
-                if (DEBUG_DISPATCH_CYCLE) {
-                    ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover "
-                          "enter event",
-                          connection->getInputChannelName().c_str());
-                }
-                // We keep the 'resolvedEventId' here equal to the original 'motionEntry.id' because
-                // this is a one-to-one event conversion.
-                dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
-            }
+            std::shared_ptr<const MotionEntry> resolvedMotion =
+                    std::static_pointer_cast<const MotionEntry>(eventEntry);
+            {
+                // Determine the resolved motion entry.
+                const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry);
+                int32_t resolvedAction = motionEntry.action;
+                int32_t resolvedFlags = motionEntry.flags;
 
-            if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_CANCEL) {
-                dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_CANCELED;
-            }
-            if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_OBSCURED)) {
-                dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
-            }
-            if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED)) {
-                dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+                if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+                    resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
+                } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
+                    resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
+                } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_ENTER)) {
+                    resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+                } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
+                    resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
+                } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
+                    resolvedAction = AMOTION_EVENT_ACTION_DOWN;
+                }
+                if (resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
+                    !connection->inputState.isHovering(motionEntry.deviceId, motionEntry.source,
+                                                       motionEntry.displayId)) {
+                    if (DEBUG_DISPATCH_CYCLE) {
+                        LOG(DEBUG) << "channel '" << connection->getInputChannelName().c_str()
+                                   << "' ~ enqueueDispatchEntryLocked: filling in missing hover "
+                                      "enter event";
+                    }
+                    resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+                }
+
+                if (resolvedAction == AMOTION_EVENT_ACTION_CANCEL) {
+                    resolvedFlags |= AMOTION_EVENT_FLAG_CANCELED;
+                }
+                if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_OBSCURED)) {
+                    resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+                }
+                if (dispatchEntry->targetFlags.test(
+                            InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED)) {
+                    resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+                }
+
+                dispatchEntry->resolvedFlags = resolvedFlags;
+                if (resolvedAction != motionEntry.action) {
+                    // Generate a new MotionEntry with a new eventId using the resolved action and
+                    // flags.
+                    resolvedMotion =
+                            std::make_shared<MotionEntry>(mIdGenerator.nextId(),
+                                                          motionEntry.injectionState,
+                                                          motionEntry.eventTime,
+                                                          motionEntry.deviceId, motionEntry.source,
+                                                          motionEntry.displayId,
+                                                          motionEntry.policyFlags, resolvedAction,
+                                                          motionEntry.actionButton, resolvedFlags,
+                                                          motionEntry.metaState,
+                                                          motionEntry.buttonState,
+                                                          motionEntry.classification,
+                                                          motionEntry.edgeFlags,
+                                                          motionEntry.xPrecision,
+                                                          motionEntry.yPrecision,
+                                                          motionEntry.xCursorPosition,
+                                                          motionEntry.yCursorPosition,
+                                                          motionEntry.downTime,
+                                                          motionEntry.pointerProperties,
+                                                          motionEntry.pointerCoords);
+                    if (ATRACE_ENABLED()) {
+                        std::string message = StringPrintf("Transmute MotionEvent(id=0x%" PRIx32
+                                                           ") to MotionEvent(id=0x%" PRIx32 ").",
+                                                           motionEntry.id, resolvedMotion->id);
+                        ATRACE_NAME(message.c_str());
+                    }
+
+                    // Set the resolved motion entry in the DispatchEntry.
+                    dispatchEntry->eventEntry = resolvedMotion;
+                    eventEntry = resolvedMotion;
+                }
             }
 
             // Check if we need to cancel any of the ongoing gestures. We don't support multiple
             // devices being active at the same time in the same window, so if a new device is
             // active, cancel the gesture from the old device.
-
             std::unique_ptr<EventEntry> cancelEvent =
-                    connection->inputState
-                            .cancelConflictingInputStream(motionEntry,
-                                                          dispatchEntry->resolvedAction);
+                    connection->inputState.cancelConflictingInputStream(*resolvedMotion);
             if (cancelEvent != nullptr) {
-                LOG(INFO) << "Canceling pointers for device " << motionEntry.deviceId << " in "
+                LOG(INFO) << "Canceling pointers for device " << resolvedMotion->deviceId << " in "
                           << connection->getInputChannelName() << " with event "
                           << cancelEvent->getDescription();
                 std::unique_ptr<DispatchEntry> cancelDispatchEntry =
@@ -3411,31 +3437,20 @@
                 connection->outboundQueue.emplace_back(std::move(cancelDispatchEntry));
             }
 
-            if (!connection->inputState.trackMotion(motionEntry, dispatchEntry->resolvedAction,
+            if (!connection->inputState.trackMotion(*resolvedMotion,
                                                     dispatchEntry->resolvedFlags)) {
                 LOG(WARNING) << "channel " << connection->getInputChannelName()
                              << "~ dropping inconsistent event: " << *dispatchEntry;
                 return; // skip the inconsistent event
             }
 
-            dispatchEntry->resolvedEventId =
-                    dispatchEntry->resolvedEventId == DEFAULT_RESOLVED_EVENT_ID
-                    ? mIdGenerator.nextId()
-                    : motionEntry.id;
-            if (ATRACE_ENABLED() && dispatchEntry->resolvedEventId != motionEntry.id) {
-                std::string message = StringPrintf("Transmute MotionEvent(id=0x%" PRIx32
-                                                   ") to MotionEvent(id=0x%" PRIx32 ").",
-                                                   motionEntry.id, dispatchEntry->resolvedEventId);
-                ATRACE_NAME(message.c_str());
-            }
-
-            if ((motionEntry.flags & AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE) &&
-                (motionEntry.policyFlags & POLICY_FLAG_TRUSTED)) {
+            if ((resolvedMotion->flags & AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE) &&
+                (resolvedMotion->policyFlags & POLICY_FLAG_TRUSTED)) {
                 // Skip reporting pointer down outside focus to the policy.
                 break;
             }
 
-            dispatchPointerDownOutsideFocus(motionEntry.source, dispatchEntry->resolvedAction,
+            dispatchPointerDownOutsideFocus(resolvedMotion->source, resolvedMotion->action,
                                             inputTarget.inputChannel->getConnectionToken());
 
             break;
@@ -3453,14 +3468,14 @@
         case EventEntry::Type::CONFIGURATION_CHANGED:
         case EventEntry::Type::DEVICE_RESET: {
             LOG_ALWAYS_FATAL("%s events should not go to apps",
-                             ftl::enum_string(newEntry.type).c_str());
+                             ftl::enum_string(eventEntry->type).c_str());
             break;
         }
     }
 
     // Remember that we are waiting for this dispatch to complete.
     if (dispatchEntry->hasForegroundTarget()) {
-        incrementPendingForegroundDispatches(newEntry);
+        incrementPendingForegroundDispatches(*eventEntry);
     }
 
     // Enqueue the dispatch entry.
@@ -3609,18 +3624,17 @@
 
     // Publish the motion event.
     return connection.inputPublisher
-            .publishMotionEvent(dispatchEntry.seq, dispatchEntry.resolvedEventId,
-                                motionEntry.deviceId, motionEntry.source, motionEntry.displayId,
-                                std::move(hmac), dispatchEntry.resolvedAction,
-                                motionEntry.actionButton, dispatchEntry.resolvedFlags,
-                                motionEntry.edgeFlags, motionEntry.metaState,
-                                motionEntry.buttonState, motionEntry.classification,
-                                dispatchEntry.transform, motionEntry.xPrecision,
-                                motionEntry.yPrecision, motionEntry.xCursorPosition,
-                                motionEntry.yCursorPosition, dispatchEntry.rawTransform,
-                                motionEntry.downTime, motionEntry.eventTime,
-                                motionEntry.getPointerCount(), motionEntry.pointerProperties.data(),
-                                usingCoords);
+            .publishMotionEvent(dispatchEntry.seq, motionEntry.id, motionEntry.deviceId,
+                                motionEntry.source, motionEntry.displayId, std::move(hmac),
+                                motionEntry.action, motionEntry.actionButton,
+                                dispatchEntry.resolvedFlags, motionEntry.edgeFlags,
+                                motionEntry.metaState, motionEntry.buttonState,
+                                motionEntry.classification, dispatchEntry.transform,
+                                motionEntry.xPrecision, motionEntry.yPrecision,
+                                motionEntry.xCursorPosition, motionEntry.yCursorPosition,
+                                dispatchEntry.rawTransform, motionEntry.downTime,
+                                motionEntry.eventTime, motionEntry.getPointerCount(),
+                                motionEntry.pointerProperties.data(), usingCoords);
 }
 
 void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
@@ -3652,14 +3666,13 @@
 
                 // Publish the key event.
                 status = connection->inputPublisher
-                                 .publishKeyEvent(dispatchEntry->seq,
-                                                  dispatchEntry->resolvedEventId, keyEntry.deviceId,
-                                                  keyEntry.source, keyEntry.displayId,
-                                                  std::move(hmac), dispatchEntry->resolvedAction,
-                                                  dispatchEntry->resolvedFlags, keyEntry.keyCode,
-                                                  keyEntry.scanCode, keyEntry.metaState,
-                                                  keyEntry.repeatCount, keyEntry.downTime,
-                                                  keyEntry.eventTime);
+                                 .publishKeyEvent(dispatchEntry->seq, keyEntry.id,
+                                                  keyEntry.deviceId, keyEntry.source,
+                                                  keyEntry.displayId, std::move(hmac),
+                                                  keyEntry.action, dispatchEntry->resolvedFlags,
+                                                  keyEntry.keyCode, keyEntry.scanCode,
+                                                  keyEntry.metaState, keyEntry.repeatCount,
+                                                  keyEntry.downTime, keyEntry.eventTime);
                 break;
             }
 
@@ -3777,7 +3790,7 @@
 
 const std::array<uint8_t, 32> InputDispatcher::getSignature(
         const MotionEntry& motionEntry, const DispatchEntry& dispatchEntry) const {
-    const int32_t actionMasked = MotionEvent::getActionMasked(dispatchEntry.resolvedAction);
+    const int32_t actionMasked = MotionEvent::getActionMasked(motionEntry.action);
     if (actionMasked != AMOTION_EVENT_ACTION_UP && actionMasked != AMOTION_EVENT_ACTION_DOWN) {
         // Only sign events up and down events as the purely move events
         // are tied to their up/down counterparts so signing would be redundant.
@@ -3795,7 +3808,6 @@
         const KeyEntry& keyEntry, const DispatchEntry& dispatchEntry) const {
     VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEntry(keyEntry);
     verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_KEY_EVENT_FLAGS;
-    verifiedEvent.action = dispatchEntry.resolvedAction;
     return sign(verifiedEvent);
 }