Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fe0126d authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Use std::map for fallback keys

Before this CL, custom data structures were used to store fallback keys.
Those structures have some known bugs. To fix this, convert to std::map
and use std::optional to store the result of fallback key lookup.

Bug: 278299254
Test: m inputflinger_tests && $ANDROID_HOST_OUT/nativetest64/inputflinger_tests/inputflinger_tests
Change-Id: Id37c41694d0b4cfa2ae107b7db13e9389d21c562
parent 25af133b
Loading
Loading
Loading
Loading
+21 −21
Original line number Diff line number Diff line
@@ -6197,7 +6197,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con
    // Get the fallback key state.
    // Clear it out after dispatching the UP.
    int32_t originalKeyCode = keyEntry.keyCode;
    int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
    std::optional<int32_t> fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
    if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
        connection->inputState.removeFallbackKey(originalKeyCode);
    }
@@ -6206,7 +6206,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con
        // If the application handles the original key for which we previously
        // generated a fallback or if the window is not a foreground window,
        // then cancel the associated fallback key, if any.
        if (fallbackKeyCode != -1) {
        if (fallbackKeyCode) {
            // Dispatch the unhandled key to the policy with the cancel flag.
            if (DEBUG_OUTBOUND_EVENT_DETAILS) {
                ALOGD("Unhandled key event: Asking policy to cancel fallback action.  "
@@ -6225,12 +6225,12 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con
            mLock.lock();

            // Cancel the fallback key.
            if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
            if (*fallbackKeyCode != AKEYCODE_UNKNOWN) {
                CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS,
                                           "application handled the original non-fallback key "
                                           "or is no longer a foreground target, "
                                           "canceling previously dispatched fallback key");
                options.keyCode = fallbackKeyCode;
                options.keyCode = *fallbackKeyCode;
                synthesizeCancelationEventsForConnectionLocked(connection, options);
            }
            connection->inputState.removeFallbackKey(originalKeyCode);
@@ -6240,7 +6240,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con
        // that we are in a good state to perform unhandled key event processing
        // Then ask the policy what to do with it.
        bool initialDown = keyEntry.action == AKEY_EVENT_ACTION_DOWN && keyEntry.repeatCount == 0;
        if (fallbackKeyCode == -1 && !initialDown) {
        if (!fallbackKeyCode && !initialDown) {
            if (DEBUG_OUTBOUND_EVENT_DETAILS) {
                ALOGD("Unhandled key event: Skipping unhandled key event processing "
                      "since this is not an initial down.  "
@@ -6275,53 +6275,53 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con
        // The fallback keycode cannot change at any other point in the lifecycle.
        if (initialDown) {
            if (fallback) {
                fallbackKeyCode = event.getKeyCode();
                *fallbackKeyCode = event.getKeyCode();
            } else {
                fallbackKeyCode = AKEYCODE_UNKNOWN;
                *fallbackKeyCode = AKEYCODE_UNKNOWN;
            }
            connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
            connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode);
        }

        ALOG_ASSERT(fallbackKeyCode != -1);
        ALOG_ASSERT(fallbackKeyCode);

        // Cancel the fallback key if the policy decides not to send it anymore.
        // We will continue to dispatch the key to the policy but we will no
        // longer dispatch a fallback key to the application.
        if (fallbackKeyCode != AKEYCODE_UNKNOWN &&
            (!fallback || fallbackKeyCode != event.getKeyCode())) {
        if (*fallbackKeyCode != AKEYCODE_UNKNOWN &&
            (!fallback || *fallbackKeyCode != event.getKeyCode())) {
            if (DEBUG_OUTBOUND_EVENT_DETAILS) {
                if (fallback) {
                    ALOGD("Unhandled key event: Policy requested to send key %d"
                          "as a fallback for %d, but on the DOWN it had requested "
                          "to send %d instead.  Fallback canceled.",
                          event.getKeyCode(), originalKeyCode, fallbackKeyCode);
                          event.getKeyCode(), originalKeyCode, *fallbackKeyCode);
                } else {
                    ALOGD("Unhandled key event: Policy did not request fallback for %d, "
                          "but on the DOWN it had requested to send %d.  "
                          "Fallback canceled.",
                          originalKeyCode, fallbackKeyCode);
                          originalKeyCode, *fallbackKeyCode);
                }
            }

            CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS,
                                       "canceling fallback, policy no longer desires it");
            options.keyCode = fallbackKeyCode;
            options.keyCode = *fallbackKeyCode;
            synthesizeCancelationEventsForConnectionLocked(connection, options);

            fallback = false;
            fallbackKeyCode = AKEYCODE_UNKNOWN;
            *fallbackKeyCode = AKEYCODE_UNKNOWN;
            if (keyEntry.action != AKEY_EVENT_ACTION_UP) {
                connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
                connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode);
            }
        }

        if (DEBUG_OUTBOUND_EVENT_DETAILS) {
            {
                std::string msg;
                const KeyedVector<int32_t, int32_t>& fallbackKeys =
                const std::map<int32_t, int32_t>& fallbackKeys =
                        connection->inputState.getFallbackKeys();
                for (size_t i = 0; i < fallbackKeys.size(); i++) {
                    msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i), fallbackKeys.valueAt(i));
                for (const auto& [key, value] : fallbackKeys) {
                    msg += StringPrintf(", %d->%d", key, value);
                }
                ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
                      fallbackKeys.size(), msg.c_str());
@@ -6335,7 +6335,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con
            keyEntry.source = event.getSource();
            keyEntry.displayId = event.getDisplayId();
            keyEntry.flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
            keyEntry.keyCode = fallbackKeyCode;
            keyEntry.keyCode = *fallbackKeyCode;
            keyEntry.scanCode = event.getScanCode();
            keyEntry.metaState = event.getMetaState();
            keyEntry.repeatCount = event.getRepeatCount();
@@ -6345,7 +6345,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& con
            if (DEBUG_OUTBOUND_EVENT_DETAILS) {
                ALOGD("Unhandled key event: Dispatching fallback key.  "
                      "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
                      originalKeyCode, fallbackKeyCode, keyEntry.metaState);
                      originalKeyCode, *fallbackKeyCode, keyEntry.metaState);
            }
            return true; // restart the event
        } else {
+10 −17
Original line number Diff line number Diff line
@@ -42,13 +42,8 @@ bool InputState::trackKey(const KeyEntry& entry, int32_t action, int32_t flags)
    switch (action) {
        case AKEY_EVENT_ACTION_UP: {
            if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) {
                for (size_t i = 0; i < mFallbackKeys.size();) {
                    if (mFallbackKeys.valueAt(i) == entry.keyCode) {
                        mFallbackKeys.removeItemsAt(i);
                    } else {
                        i += 1;
                    }
                }
                std::erase_if(mFallbackKeys,
                              [&entry](const auto& item) { return item.second == entry.keyCode; });
            }
            ssize_t index = findKeyMemento(entry);
            if (index >= 0) {
@@ -481,22 +476,20 @@ void InputState::mergePointerStateTo(InputState& other) {
    }
}

int32_t InputState::getFallbackKey(int32_t originalKeyCode) {
    ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
    return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
std::optional<int32_t> InputState::getFallbackKey(int32_t originalKeyCode) {
    auto it = mFallbackKeys.find(originalKeyCode);
    if (it == mFallbackKeys.end()) {
        return {};
    }
    return it->second;
}

void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
    ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
    if (index >= 0) {
        mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
    } else {
        mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
    }
    mFallbackKeys.insert_or_assign(originalKeyCode, fallbackKeyCode);
}

void InputState::removeFallbackKey(int32_t originalKeyCode) {
    mFallbackKeys.removeItem(originalKeyCode);
    mFallbackKeys.erase(originalKeyCode);
}

bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
+4 −4
Original line number Diff line number Diff line
@@ -62,9 +62,9 @@ public:
    void mergePointerStateTo(InputState& other);

    // Gets the fallback key associated with a keycode.
    // Returns -1 if none.
    // Returns std::nullopt if none.
    // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
    int32_t getFallbackKey(int32_t originalKeyCode);
    std::optional<int32_t> getFallbackKey(int32_t originalKeyCode);

    // Sets the fallback key for a particular keycode.
    void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
@@ -72,7 +72,7 @@ public:
    // Removes the fallback key for a particular keycode.
    void removeFallbackKey(int32_t originalKeyCode);

    inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const { return mFallbackKeys; }
    inline const std::map<int32_t, int32_t>& getFallbackKeys() const { return mFallbackKeys; }

private:
    struct KeyMemento {
@@ -113,7 +113,7 @@ private:

    std::vector<KeyMemento> mKeyMementos;
    std::vector<MotionMemento> mMotionMementos;
    KeyedVector<int32_t, int32_t> mFallbackKeys;
    std::map</*originalKeyCode*/int32_t, /*fallbackKeyCode*/int32_t> mFallbackKeys;

    ssize_t findKeyMemento(const KeyEntry& entry) const;
    ssize_t findMotionMemento(const MotionEntry& entry, bool hovering) const;