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

Commit b0237800 authored by Arthur Hung's avatar Arthur Hung Committed by Android (Google) Code Review
Browse files

Merge "Reset intercept key wake time when receving up event" into tm-dev

parents a6506333 2ee6d0ba
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -1032,6 +1032,21 @@ bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newE
                    }
                }
            }

            // If a new up event comes in, and the pending event with same key code has been asked
            // to try again later because of the policy. We have to reset the intercept key wake up
            // time for it may have been handled in the policy and could be dropped.
            if (keyEntry.action == AKEY_EVENT_ACTION_UP && mPendingEvent &&
                mPendingEvent->type == EventEntry::Type::KEY) {
                KeyEntry& pendingKey = static_cast<KeyEntry&>(*mPendingEvent);
                if (pendingKey.keyCode == keyEntry.keyCode &&
                    pendingKey.interceptKeyResult ==
                            KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
                    pendingKey.interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
                    pendingKey.interceptKeyWakeupTime = 0;
                    needWake = true;
                }
            }
            break;
        }

+63 −2
Original line number Diff line number Diff line
@@ -289,6 +289,13 @@ public:
        ASSERT_EQ(token, *receivedToken);
    }

    /**
     * Set policy timeout. A value of zero means next key will not be intercepted.
     */
    void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
        mInterceptKeyTimeout = timeout;
    }

private:
    std::mutex mLock;
    std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
@@ -311,6 +318,8 @@ private:
    sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
    bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;

    std::chrono::milliseconds mInterceptKeyTimeout = 0ms;

    // All three ANR-related callbacks behave the same way, so we use this generic function to wait
    // for a specific container to become non-empty. When the container is non-empty, return the
    // first entry from the container and erase it.
@@ -429,12 +438,20 @@ private:
        return true;
    }

    void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
    void interceptKeyBeforeQueueing(const KeyEvent* inputEvent, uint32_t&) override {
        if (inputEvent->getAction() == AKEY_EVENT_ACTION_UP) {
            // Clear intercept state when we handled the event.
            mInterceptKeyTimeout = 0ms;
        }
    }

    void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}

    nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
        return 0;
        nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
        // Clear intercept state so we could dispatch the event in next wake.
        mInterceptKeyTimeout = 0ms;
        return delay;
    }

    bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
@@ -2182,6 +2199,50 @@ TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
                         0 /*expectedFlags*/);
}

TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window =
            new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
    window->setFocusable(true);

    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
    setFocusedWindow(window);

    window->consumeFocusEvent(true);

    NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
    const std::chrono::milliseconds interceptKeyTimeout = 50ms;
    const nsecs_t injectTime = keyArgs.eventTime;
    mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
    mDispatcher->notifyKey(&keyArgs);
    // The dispatching time should be always greater than or equal to intercept key timeout.
    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
    ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
                std::chrono::nanoseconds(interceptKeyTimeout).count());
}

TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window =
            new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
    window->setFocusable(true);

    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
    setFocusedWindow(window);

    window->consumeFocusEvent(true);

    NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
    NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
    mFakePolicy->setInterceptKeyTimeout(150ms);
    mDispatcher->notifyKey(&keyDown);
    mDispatcher->notifyKey(&keyUp);

    // Window should receive key event immediately when same key up.
    window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
    window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
}

/**
 * Ensure the correct coordinate spaces are used by InputDispatcher.
 *