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

Commit 5f8f6692 authored by Tiger Huang's avatar Tiger Huang Committed by Android (Google) Code Review
Browse files

Merge "Track focus changes on external displays (1/4)"

parents 317b9638 721e26f1
Loading
Loading
Loading
Loading
+163 −46
Original line number Diff line number Diff line
@@ -235,6 +235,12 @@ static void dumpRegion(std::string& dump, const Region& region) {
    }
}

template<typename T, typename U>
static T getValueByKey(std::unordered_map<U, T>& map, U key) {
    typename std::unordered_map<U, T>::const_iterator it = map.find(key);
    return it != map.end() ? it->second : T{};
}


// --- InputDispatcher ---

@@ -244,6 +250,7 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic
    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
    mNextUnblockedEvent(nullptr),
    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
    mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
    mLooper = new Looper(false);

@@ -808,8 +815,10 @@ bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            CommandEntry* commandEntry = postCommandLocked(
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            if (mFocusedWindowHandle != nullptr) {
                commandEntry->inputWindowHandle = mFocusedWindowHandle;
            sp<InputWindowHandle> focusedWindowHandle =
                    getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
            if (focusedWindowHandle != nullptr) {
                commandEntry->inputWindowHandle = focusedWindowHandle;
            }
            commandEntry->keyEntry = entry;
            entry->refCount += 1;
@@ -1108,17 +1117,49 @@ void InputDispatcher::resetANRTimeoutsLocked() {
    mInputTargetWaitApplicationHandle.clear();
}

/**
 * Get the display id that the given event should go to. If this event specifies a valid display id,
 * then it should be dispatched to that display. Otherwise, the event goes to the focused display.
 * Focused display is the display that the user most recently interacted with.
 */
int32_t InputDispatcher::getTargetDisplayId(const EventEntry* entry) {
    int32_t displayId;
    switch (entry->type) {
    case EventEntry::TYPE_KEY: {
        const KeyEntry* typedEntry = static_cast<const KeyEntry*>(entry);
        displayId = typedEntry->displayId;
        break;
    }
    case EventEntry::TYPE_MOTION: {
        const MotionEntry* typedEntry = static_cast<const MotionEntry*>(entry);
        displayId = typedEntry->displayId;
        break;
    }
    default: {
        ALOGE("Unsupported event type '%" PRId32 "' for target display.", entry->type);
        return ADISPLAY_ID_NONE;
    }
    }
    return displayId == ADISPLAY_ID_NONE ? mFocusedDisplayId : displayId;
}

int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
        const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
    int32_t injectionResult;
    std::string reason;

    int32_t displayId = getTargetDisplayId(entry);
    sp<InputWindowHandle> focusedWindowHandle =
            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
    sp<InputApplicationHandle> focusedApplicationHandle =
            getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);

    // If there is no currently focused window and no focused application
    // then drop the event.
    if (mFocusedWindowHandle == nullptr) {
        if (mFocusedApplicationHandle != nullptr) {
    if (focusedWindowHandle == nullptr) {
        if (focusedApplicationHandle != nullptr) {
            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
                    mFocusedApplicationHandle, nullptr, nextWakeupTime,
                    focusedApplicationHandle, nullptr, nextWakeupTime,
                    "Waiting because no window has focus but there is a "
                    "focused application that may eventually add a window "
                    "when it finishes starting up.");
@@ -1131,23 +1172,23 @@ int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
    }

    // Check permissions.
    if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
    if (!checkInjectionPermission(focusedWindowHandle, entry->injectionState)) {
        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
        goto Failed;
    }

    // Check whether the window is ready for more input.
    reason = checkWindowReadyForMoreInputLocked(currentTime,
            mFocusedWindowHandle, entry, "focused");
            focusedWindowHandle, entry, "focused");
    if (!reason.empty()) {
        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
                mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.c_str());
                focusedApplicationHandle, focusedWindowHandle, nextWakeupTime, reason.c_str());
        goto Unresponsive;
    }

    // Success!  Output targets.
    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
    addWindowTargetLocked(mFocusedWindowHandle,
    addWindowTargetLocked(focusedWindowHandle,
            InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
            inputTargets);

@@ -1802,8 +1843,11 @@ std::string InputDispatcher::getApplicationWindowLabelLocked(
}

void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
    if (mFocusedWindowHandle != nullptr) {
        const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
    int32_t displayId = getTargetDisplayId(eventEntry);
    sp<InputWindowHandle> focusedWindowHandle =
            getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
    if (focusedWindowHandle != nullptr) {
        const InputWindowInfo* info = focusedWindowHandle->getInfo();
        if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
#if DEBUG_DISPATCH_CYCLE
            ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str());
@@ -2978,18 +3022,7 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& input
        // Copy old handles for release if they are no longer present.
        const Vector<sp<InputWindowHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);

        // TODO(b/111361570): multi-display focus, one focus window per display.
        sp<InputWindowHandle> newFocusedWindowHandle = mFocusedWindowHandle;
        // Reset newFocusedWindowHandle to nullptr if current display own the focus window,
        // that will be updated below when going through all window handles in current display.
        // And if list of window handles becomes empty then it will be updated by other display.
        if (mFocusedWindowHandle != nullptr) {
            const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
            if (info == nullptr || info->displayId == displayId) {
                newFocusedWindowHandle = nullptr;
            }
        }

        sp<InputWindowHandle> newFocusedWindowHandle = nullptr;
        bool foundHoveredWindow = false;

        if (inputWindowHandles.isEmpty()) {
@@ -3026,28 +3059,31 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& input
            mLastHoverWindowHandle = nullptr;
        }

        // TODO(b/111361570): multi-display focus, one focus in all display in current.
        if (mFocusedWindowHandle != newFocusedWindowHandle) {
            if (mFocusedWindowHandle != nullptr) {
        sp<InputWindowHandle> oldFocusedWindowHandle =
                getValueByKey(mFocusedWindowHandlesByDisplay, displayId);

        if (oldFocusedWindowHandle != newFocusedWindowHandle) {
            if (oldFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
                ALOGD("Focus left window: %s",
                        mFocusedWindowHandle->getName().c_str());
                        oldFocusedWindowHandle->getName().c_str());
#endif
                sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
                sp<InputChannel> focusedInputChannel = oldFocusedWindowHandle->getInputChannel();
                if (focusedInputChannel != nullptr) {
                    CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                            "focus left window");
                    synthesizeCancelationEventsForInputChannelLocked(
                            focusedInputChannel, options);
                }
                mFocusedWindowHandlesByDisplay.erase(displayId);
            }
            if (newFocusedWindowHandle != nullptr) {
#if DEBUG_FOCUS
                ALOGD("Focus entered window: %s",
                        newFocusedWindowHandle->getName().c_str());
#endif
                mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
            }
            mFocusedWindowHandle = newFocusedWindowHandle;
        }

        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
@@ -3096,25 +3132,28 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle>>& input
}

void InputDispatcher::setFocusedApplication(
        const sp<InputApplicationHandle>& inputApplicationHandle) {
        int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) {
#if DEBUG_FOCUS
    ALOGD("setFocusedApplication");
#endif
    { // acquire lock
        AutoMutex _l(mLock);

        sp<InputApplicationHandle> oldFocusedApplicationHandle =
                getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
        if (inputApplicationHandle != nullptr && inputApplicationHandle->updateInfo()) {
            if (mFocusedApplicationHandle != inputApplicationHandle) {
                if (mFocusedApplicationHandle != nullptr) {
            if (oldFocusedApplicationHandle != inputApplicationHandle) {
                if (oldFocusedApplicationHandle != nullptr) {
                    resetANRTimeoutsLocked();
                    mFocusedApplicationHandle->releaseInfo();
                    oldFocusedApplicationHandle->releaseInfo();
                }
                mFocusedApplicationHandle = inputApplicationHandle;
                mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
            }
        } else if (mFocusedApplicationHandle != nullptr) {
        } else if (oldFocusedApplicationHandle != nullptr) {
            resetANRTimeoutsLocked();
            mFocusedApplicationHandle->releaseInfo();
            mFocusedApplicationHandle.clear();
            oldFocusedApplicationHandle->releaseInfo();
            oldFocusedApplicationHandle.clear();
            mFocusedApplicationHandlesByDisplay.erase(displayId);
        }

#if DEBUG_FOCUS
@@ -3126,6 +3165,62 @@ void InputDispatcher::setFocusedApplication(
    mLooper->wake();
}

/**
 * Sets the focused display, which is responsible for receiving focus-dispatched input events where
 * the display not specified.
 *
 * We track any unreleased events for each window. If a window loses the ability to receive the
 * released event, we will send a cancel event to it. So when the focused display is changed, we
 * cancel all the unreleased display-unspecified events for the focused window on the old focused
 * display. The display-specified events won't be affected.
 */
void InputDispatcher::setFocusedDisplay(int32_t displayId) {
#if DEBUG_FOCUS
    ALOGD("setFocusedDisplay displayId=%" PRId32, displayId);
#endif
    { // acquire lock
        AutoMutex _l(mLock);

        if (mFocusedDisplayId != displayId) {
            sp<InputWindowHandle> oldFocusedWindowHandle =
                    getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId);
            if (oldFocusedWindowHandle != nullptr) {
                sp<InputChannel> inputChannel = oldFocusedWindowHandle->getInputChannel();
                if (inputChannel != nullptr) {
                    CancelationOptions options(
                            CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS,
                            "The display which contains this window no longer has focus.");
                    synthesizeCancelationEventsForInputChannelLocked(inputChannel, options);
                }
            }
            mFocusedDisplayId = displayId;

            // Sanity check
            sp<InputWindowHandle> newFocusedWindowHandle =
                    getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
            if (newFocusedWindowHandle == nullptr) {
                ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
                if (!mFocusedWindowHandlesByDisplay.empty()) {
                    ALOGE("But another display has a focused window:");
                    for (auto& it : mFocusedWindowHandlesByDisplay) {
                        const int32_t displayId = it.first;
                        const sp<InputWindowHandle>& windowHandle = it.second;
                        ALOGE("Display #%" PRId32 " has focused window: '%s'\n",
                                displayId, windowHandle->getName().c_str());
                    }
                }
            }
        }

#if DEBUG_FOCUS
        logDispatchStateLocked();
#endif
    } // release lock

    // Wake up poll loop since it may need to make new input dispatching choices.
    mLooper->wake();
}

void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
#if DEBUG_FOCUS
    ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
@@ -3152,7 +3247,7 @@ void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
        }

#if DEBUG_FOCUS
        //logDispatchStateLocked();
        logDispatchStateLocked();
#endif
    } // release lock

@@ -3297,17 +3392,35 @@ void InputDispatcher::logDispatchStateLocked() {
void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
    dump += StringPrintf(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
    dump += StringPrintf(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);

    if (mFocusedApplicationHandle != nullptr) {
        dump += StringPrintf(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
                mFocusedApplicationHandle->getName().c_str(),
                mFocusedApplicationHandle->getDispatchingTimeout(
    dump += StringPrintf(INDENT "FocusedDisplayId: %" PRId32 "\n", mFocusedDisplayId);

    if (!mFocusedApplicationHandlesByDisplay.empty()) {
        dump += StringPrintf(INDENT "FocusedApplications:\n");
        for (auto& it : mFocusedApplicationHandlesByDisplay) {
            const int32_t displayId = it.first;
            const sp<InputApplicationHandle>& applicationHandle = it.second;
            dump += StringPrintf(
                    INDENT2 "displayId=%" PRId32 ", name='%s', dispatchingTimeout=%0.3fms\n",
                    displayId,
                    applicationHandle->getName().c_str(),
                    applicationHandle->getDispatchingTimeout(
                            DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
        }
    } else {
        dump += StringPrintf(INDENT "FocusedApplications: <none>\n");
    }

    if (!mFocusedWindowHandlesByDisplay.empty()) {
        dump += StringPrintf(INDENT "FocusedWindows:\n");
        for (auto& it : mFocusedWindowHandlesByDisplay) {
            const int32_t displayId = it.first;
            const sp<InputWindowHandle>& windowHandle = it.second;
            dump += StringPrintf(INDENT2 "displayId=%" PRId32 ", name='%s'\n",
                    displayId, windowHandle->getName().c_str());
        }
    } else {
        dump += StringPrintf(INDENT "FocusedApplication: <null>\n");
        dump += StringPrintf(INDENT "FocusedWindows: <none>\n");
    }
    dump += StringPrintf(INDENT "FocusedWindow: name='%s'\n",
            mFocusedWindowHandle != nullptr ? mFocusedWindowHandle->getName().c_str() : "<null>");

    if (!mTouchStatesByDisplay.isEmpty()) {
        dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
@@ -4527,6 +4640,8 @@ bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
        return true;
    case CancelationOptions::CANCEL_FALLBACK_EVENTS:
        return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
    case CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS:
        return memento.displayId == ADISPLAY_ID_NONE;
    default:
        return false;
    }
@@ -4545,6 +4660,8 @@ bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& mement
        return memento.source & AINPUT_SOURCE_CLASS_POINTER;
    case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
        return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
    case CancelationOptions::CANCEL_DISPLAY_UNSPECIFIED_EVENTS:
        return memento.displayId == ADISPLAY_ID_NONE;
    default:
        return false;
    }
+22 −6
Original line number Diff line number Diff line
@@ -311,12 +311,18 @@ public:
    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
            int32_t displayId) = 0;

    /* Sets the focused application.
    /* Sets the focused application on the given display.
     *
     * This method may be called on any thread (usually by the input manager).
     */
    virtual void setFocusedApplication(
            const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
            int32_t displayId, const sp<InputApplicationHandle>& inputApplicationHandle) = 0;

    /* Sets the focused display.
     *
     * This method may be called on any thread (usually by the input manager).
     */
    virtual void setFocusedDisplay(int32_t displayId) = 0;

    /* Sets the input dispatching mode.
     *
@@ -391,7 +397,9 @@ public:

    virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles,
            int32_t displayId);
    virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
    virtual void setFocusedApplication(int32_t displayId,
            const sp<InputApplicationHandle>& inputApplicationHandle);
    virtual void setFocusedDisplay(int32_t displayId);
    virtual void setInputDispatchMode(bool enabled, bool frozen);
    virtual void setInputFilterEnabled(bool enabled);

@@ -686,6 +694,10 @@ private:
            CANCEL_POINTER_EVENTS = 1,
            CANCEL_NON_POINTER_EVENTS = 2,
            CANCEL_FALLBACK_EVENTS = 3,

            /* Cancel events where the display not specified. These events would go to the focused
             * display. */
            CANCEL_DISPLAY_UNSPECIFIED_EVENTS = 4,
        };

        // The criterion to use to determine which events should be canceled.
@@ -966,7 +978,7 @@ private:
    bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;

    // Focus tracking for keys, trackball, etc.
    sp<InputWindowHandle> mFocusedWindowHandle;
    std::unordered_map<int32_t, sp<InputWindowHandle>> mFocusedWindowHandlesByDisplay;

    // Focus tracking for touch.
    struct TouchedWindow {
@@ -997,8 +1009,11 @@ private:
    KeyedVector<int32_t, TouchState> mTouchStatesByDisplay;
    TouchState mTempTouchState;

    // Focused application.
    sp<InputApplicationHandle> mFocusedApplicationHandle;
    // Focused applications.
    std::unordered_map<int32_t, sp<InputApplicationHandle>> mFocusedApplicationHandlesByDisplay;

    // Top focused display.
    int32_t mFocusedDisplayId;

    // Dispatcher state at time of last ANR.
    std::string mLastANRState;
@@ -1046,6 +1061,7 @@ private:
    nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
    void resetANRTimeoutsLocked();

    int32_t getTargetDisplayId(const EventEntry* entry);
    int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
            Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime);
    int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
+20 −7
Original line number Diff line number Diff line
@@ -382,12 +382,13 @@ public:
        int32_t mDisplayId;
};

static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher) {
static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
        int32_t displayId = ADISPLAY_ID_NONE) {
    KeyEvent event;
    nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);

    // Define a valid key down event.
    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
            AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
            AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);

@@ -466,7 +467,7 @@ TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
    sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second");

    // Set focus application.
    mDispatcher->setFocusedApplication(application);
    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);

    // Expect one focus window exist in display.
    windowSecond->setFocus();
@@ -511,15 +512,21 @@ TEST_F(InputDispatcherTest, SetInputWindow_MultiDisplayTouch) {
    windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
}

// TODO(b/111361570): multi-display focus, one focus window per display.
TEST_F(InputDispatcherTest, SetInputWindow_FocusedInMultiDisplay) {
    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
    sp<FakeWindowHandle> windowInPrimary = new FakeWindowHandle(application, mDispatcher, "D_1");
    sp<FakeApplicationHandle> application2 = new FakeApplicationHandle();
    sp<FakeWindowHandle> windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2");

    constexpr int32_t SECOND_DISPLAY_ID = 1;

    // Set focus to primary display window.
    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
    windowInPrimary->setFocus();

    // Set focus to second display window.
    mDispatcher->setFocusedApplication(application2);
    mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
    mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
    windowInSecondary->setFocus();

    // Update all windows per displays.
@@ -527,13 +534,18 @@ TEST_F(InputDispatcherTest, SetInputWindow_FocusedInMultiDisplay) {
    inputWindowHandles.push(windowInPrimary);
    mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);

    constexpr int32_t SECOND_DISPLAY_ID = 1;
    windowInSecondary->setDisplayId(SECOND_DISPLAY_ID);
    Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
    inputWindowHandles_Second.push(windowInSecondary);
    mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);

    // Test inject a key down.
    // Test inject a key down with display id specified.
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
            << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
    windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
    windowInSecondary->assertNoEvents();

    // Test inject a key down without display id specified.
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
            << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
    windowInPrimary->assertNoEvents();
@@ -545,6 +557,7 @@ TEST_F(InputDispatcherTest, SetInputWindow_FocusedInMultiDisplay) {

    // Expect old focus should receive a cancel event.
    windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
    // TODO(b/111361570): Validate that the event here was marked as canceled.

    // Test inject a key down, should timeout because of no target window.
    ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))