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

Commit fc55603a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Id0c3cf19,Id089db27,Ia4c0cbb8

* changes:
  Ensure returned event is non-null
  Stricter validation of motion events in dispatcher
  Add test for hover events over spy window
parents 9f6581d7 e9349e7a
Loading
Loading
Loading
Loading
+14 −22
Original line number Original line Diff line number Diff line
@@ -148,21 +148,23 @@ bool validateKeyEvent(int32_t action) {
}
}


bool isValidMotionAction(int32_t action, int32_t actionButton, int32_t pointerCount) {
bool isValidMotionAction(int32_t action, int32_t actionButton, int32_t pointerCount) {
    switch (action & AMOTION_EVENT_ACTION_MASK) {
    switch (MotionEvent::getActionMasked(action)) {
        case AMOTION_EVENT_ACTION_DOWN:
        case AMOTION_EVENT_ACTION_DOWN:
        case AMOTION_EVENT_ACTION_UP:
        case AMOTION_EVENT_ACTION_UP:
        case AMOTION_EVENT_ACTION_CANCEL:
            return pointerCount == 1;
        case AMOTION_EVENT_ACTION_MOVE:
        case AMOTION_EVENT_ACTION_MOVE:
        case AMOTION_EVENT_ACTION_OUTSIDE:
        case AMOTION_EVENT_ACTION_HOVER_ENTER:
        case AMOTION_EVENT_ACTION_HOVER_ENTER:
        case AMOTION_EVENT_ACTION_HOVER_MOVE:
        case AMOTION_EVENT_ACTION_HOVER_MOVE:
        case AMOTION_EVENT_ACTION_HOVER_EXIT:
        case AMOTION_EVENT_ACTION_HOVER_EXIT:
            return pointerCount >= 1;
        case AMOTION_EVENT_ACTION_CANCEL:
        case AMOTION_EVENT_ACTION_OUTSIDE:
        case AMOTION_EVENT_ACTION_SCROLL:
        case AMOTION_EVENT_ACTION_SCROLL:
            return true;
            return true;
        case AMOTION_EVENT_ACTION_POINTER_DOWN:
        case AMOTION_EVENT_ACTION_POINTER_DOWN:
        case AMOTION_EVENT_ACTION_POINTER_UP: {
        case AMOTION_EVENT_ACTION_POINTER_UP: {
            int32_t index = getMotionEventActionPointerIndex(action);
            const int32_t index = MotionEvent::getActionIndex(action);
            return index >= 0 && index < pointerCount;
            return index >= 0 && index < pointerCount && pointerCount > 1;
        }
        }
        case AMOTION_EVENT_ACTION_BUTTON_PRESS:
        case AMOTION_EVENT_ACTION_BUTTON_PRESS:
        case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
        case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
@@ -2096,7 +2098,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked(


    bool isSplit = shouldSplitTouch(tempTouchState, entry);
    bool isSplit = shouldSplitTouch(tempTouchState, entry);
    const bool switchedDevice = (oldState != nullptr) &&
    const bool switchedDevice = (oldState != nullptr) &&
            (tempTouchState.deviceId != entry.deviceId || tempTouchState.source != entry.source);
            (oldState->deviceId != entry.deviceId || oldState->source != entry.source);


    const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
    const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
                                maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
                                maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
@@ -2104,6 +2106,7 @@ std::vector<TouchedWindow> InputDispatcher::findTouchedWindowTargetsLocked(
    const bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
    const bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
                             maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);
                             maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);
    const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
    const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);

    if (newGesture) {
    if (newGesture) {
        bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
        bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
        if (switchedDevice && tempTouchState.isDown() && !down && !isHoverAction) {
        if (switchedDevice && tempTouchState.isDown() && !down && !isHoverAction) {
@@ -2995,6 +2998,8 @@ void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
                             connection->getInputChannelName().c_str(), eventEntry->id);
                             connection->getInputChannelName().c_str(), eventEntry->id);
        ATRACE_NAME(message.c_str());
        ATRACE_NAME(message.c_str());
    }
    }
    LOG_ALWAYS_FATAL_IF(!inputTarget.flags.any(InputTarget::DISPATCH_MASK),
                        "No dispatch flags are set for %s", eventEntry->getDescription().c_str());


    const bool wasEmpty = connection->outboundQueue.empty();
    const bool wasEmpty = connection->outboundQueue.empty();


@@ -4053,10 +4058,9 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
                  args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
                  args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
        }
        }
    }
    }
    if (!validateMotionEvent(args->action, args->actionButton, args->pointerCount,
    LOG_ALWAYS_FATAL_IF(!validateMotionEvent(args->action, args->actionButton, args->pointerCount,
                             args->pointerProperties)) {
                                             args->pointerProperties),
        return;
                        "Invalid event: %s", args->dump().c_str());
    }


    uint32_t policyFlags = args->policyFlags;
    uint32_t policyFlags = args->policyFlags;
    policyFlags |= POLICY_FLAG_TRUSTED;
    policyFlags |= POLICY_FLAG_TRUSTED;
@@ -4981,10 +4985,6 @@ void InputDispatcher::setFocusedDisplay(int32_t displayId) {
                }
                }
            }
            }
        }
        }

        if (DEBUG_FOCUS) {
            logDispatchStateLocked();
        }
    } // release lock
    } // release lock


    // Wake up poll loop since it may need to make new input dispatching choices.
    // Wake up poll loop since it may need to make new input dispatching choices.
@@ -5015,10 +5015,6 @@ void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
        } else {
        } else {
            changed = false;
            changed = false;
        }
        }

        if (DEBUG_FOCUS) {
            logDispatchStateLocked();
        }
    } // release lock
    } // release lock


    if (changed) {
    if (changed) {
@@ -5193,10 +5189,6 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<
            synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
            synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
            synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection);
            synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection);
        }
        }

        if (DEBUG_FOCUS) {
            logDispatchStateLocked();
        }
    } // release lock
    } // release lock


    // Wake up poll loop since it may need to make new input dispatching choices.
    // Wake up poll loop since it may need to make new input dispatching choices.
+1 −2
Original line number Original line Diff line number Diff line
@@ -34,8 +34,7 @@ void TouchState::reset() {
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
                                   ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
                                   ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
                                   std::optional<nsecs_t> eventTime) {
                                   std::optional<nsecs_t> eventTime) {
    for (size_t i = 0; i < windows.size(); i++) {
    for (TouchedWindow& touchedWindow : windows) {
        TouchedWindow& touchedWindow = windows[i];
        if (touchedWindow.windowHandle == windowHandle) {
        if (touchedWindow.windowHandle == windowHandle) {
            touchedWindow.targetFlags |= targetFlags;
            touchedWindow.targetFlags |= targetFlags;
            if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
            if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
+79 −48
Original line number Original line Diff line number Diff line
@@ -110,6 +110,13 @@ MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
        *result_listener << "expected action " << MotionEvent::actionToString(action)
        *result_listener << "expected action " << MotionEvent::actionToString(action)
                         << ", but got " << MotionEvent::actionToString(arg.getAction());
                         << ", but got " << MotionEvent::actionToString(arg.getAction());
    }
    }
    if (action == AMOTION_EVENT_ACTION_DOWN) {
        if (!matches) {
            *result_listener << "; ";
        }
        *result_listener << "downTime should match eventTime for ACTION_DOWN events";
        matches &= arg.getDownTime() == arg.getEventTime();
    }
    if (action == AMOTION_EVENT_ACTION_CANCEL) {
    if (action == AMOTION_EVENT_ACTION_CANCEL) {
        if (!matches) {
        if (!matches) {
            *result_listener << "; ";
            *result_listener << "; ";
@@ -120,6 +127,10 @@ MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
    return matches;
    return matches;
}
}


MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
    return arg.getDownTime() == downTime;
}

MATCHER_P(WithSource, source, "InputEvent with specified source") {
MATCHER_P(WithSource, source, "InputEvent with specified source") {
    *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
    *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
                     << inputEventSourceToString(arg.getSource());
                     << inputEventSourceToString(arg.getSource());
@@ -1210,6 +1221,7 @@ public:
    void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
    void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
                                              int32_t expectedFlags = 0) {
                                              int32_t expectedFlags = 0) {
        InputEvent* event = consume();
        InputEvent* event = consume();
        ASSERT_NE(nullptr, event);
        ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
        ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
        const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
        const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
        EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
        EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
@@ -1231,7 +1243,7 @@ public:


    void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
    void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
        MotionEvent* motionEvent = consumeMotion();
        MotionEvent* motionEvent = consumeMotion();
        ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event";
        ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
        ASSERT_THAT(*motionEvent, matcher);
        ASSERT_THAT(*motionEvent, matcher);
    }
    }


@@ -2056,6 +2068,7 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {


    mDispatcher->waitForIdle();
    mDispatcher->waitForIdle();
    InputEvent* inputEvent1 = window1->consume();
    InputEvent* inputEvent1 = window1->consume();
    ASSERT_NE(inputEvent1, nullptr);
    window2->assertNoEvents();
    window2->assertNoEvents();
    MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
    MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
    nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
    nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
@@ -2065,6 +2078,7 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
    mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
    mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
    mDispatcher->waitForIdle();
    mDispatcher->waitForIdle();
    InputEvent* inputEvent2 = window2->consume();
    InputEvent* inputEvent2 = window2->consume();
    ASSERT_NE(inputEvent2, nullptr);
    MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
    MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
    nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
    nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
    ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
    ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
@@ -2074,17 +2088,13 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
    mDispatcher->notifyMotion(
    mDispatcher->notifyMotion(
            &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
            &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
    mDispatcher->waitForIdle();
    mDispatcher->waitForIdle();
    InputEvent* inputEvent3 = window2->consume();
    window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
    MotionEvent& motionEvent3 = static_cast<MotionEvent&>(*inputEvent3);
    ASSERT_EQ(motionEvent3.getDownTime(), downTimeForWindow2);


    // Now add new touch down on the second window
    // Now add new touch down on the second window
    mDispatcher->notifyMotion(
    mDispatcher->notifyMotion(
            &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
            &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
    mDispatcher->waitForIdle();
    mDispatcher->waitForIdle();
    InputEvent* inputEvent4 = window2->consume();
    window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
    MotionEvent& motionEvent4 = static_cast<MotionEvent&>(*inputEvent4);
    ASSERT_EQ(motionEvent4.getDownTime(), downTimeForWindow2);


    // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
    // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
    window1->consumeMotionMove();
    window1->consumeMotionMove();
@@ -2094,16 +2104,12 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
    mDispatcher->notifyMotion(
    mDispatcher->notifyMotion(
            &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}})));
            &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}})));
    mDispatcher->waitForIdle();
    mDispatcher->waitForIdle();
    InputEvent* inputEvent5 = window1->consume();
    window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
    MotionEvent& motionEvent5 = static_cast<MotionEvent&>(*inputEvent5);
    ASSERT_EQ(motionEvent5.getDownTime(), downTimeForWindow1);


    mDispatcher->notifyMotion(&(
    mDispatcher->notifyMotion(&(
            args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
            args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
    mDispatcher->waitForIdle();
    mDispatcher->waitForIdle();
    InputEvent* inputEvent6 = window1->consume();
    window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
    MotionEvent& motionEvent6 = static_cast<MotionEvent&>(*inputEvent6);
    ASSERT_EQ(motionEvent6.getDownTime(), downTimeForWindow1);
}
}


TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
@@ -2128,10 +2134,8 @@ TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
                                                         .x(900)
                                                         .x(900)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
    windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
                              ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
    windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
    windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
                              ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);


    // Move cursor into left window
    // Move cursor into left window
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -2142,12 +2146,9 @@ TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
                                                         .x(300)
                                                         .x(300)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
    windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
                              ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
    windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
    windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
    windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
                             ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
    windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
                             ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);


    // Inject a series of mouse events for a mouse click
    // Inject a series of mouse events for a mouse click
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -2170,8 +2171,7 @@ TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
                                                         .x(300)
                                                         .x(300)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
    windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
                             ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);


    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher,
              injectMotionEvent(mDispatcher,
@@ -2183,8 +2183,7 @@ TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
                                                         .x(300)
                                                         .x(300)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
    windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
                             ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);


    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher,
              injectMotionEvent(mDispatcher,
@@ -2205,12 +2204,47 @@ TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
                                                         .x(900)
                                                         .x(900)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
    windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
                             ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
    windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
    windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
    windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
                              ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);

    windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
    // No more events
                              ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
    windowLeft->assertNoEvents();
    windowRight->assertNoEvents();
}

TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();

    sp<FakeWindowHandle> spyWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
    spyWindow->setFrame(Rect(0, 0, 600, 800));
    spyWindow->setTrustedOverlay(true);
    spyWindow->setSpy(true);
    sp<FakeWindowHandle> window =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
    window->setFrame(Rect(0, 0, 600, 800));

    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});

    // Send mouse cursor to the window
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher,
                                MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
                                                   AINPUT_SOURCE_MOUSE)
                                        .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
                                                         .x(100)
                                                         .y(100))
                                        .build()));

    window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
                                     WithSource(AINPUT_SOURCE_MOUSE)));
    spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
                                        WithSource(AINPUT_SOURCE_MOUSE)));

    window->assertNoEvents();
    spyWindow->assertNoEvents();
}
}


// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
@@ -2233,8 +2267,7 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
                                                         .x(300)
                                                         .x(300)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
                         ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);


    // Inject a series of mouse events for a mouse click
    // Inject a series of mouse events for a mouse click
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -2257,8 +2290,7 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
                                                         .x(300)
                                                         .x(300)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
                         ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);


    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher,
              injectMotionEvent(mDispatcher,
@@ -2270,8 +2302,7 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
                                                         .x(300)
                                                         .x(300)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
                         ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);


    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher,
              injectMotionEvent(mDispatcher,
@@ -2291,8 +2322,7 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
                                                         .x(300)
                                                         .x(300)
                                                         .y(400))
                                                         .y(400))
                                        .build()));
                                        .build()));
    window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
    window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
                         ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
}
}


/**
/**
@@ -2362,14 +2392,13 @@ TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
                                                         .x(300)
                                                         .x(300)
                                                         .y(600))
                                                         .y(600))
                                        .build()));
                                        .build()));
    windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
    windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
                                       ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
    windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
    windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
                                       ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);


    // Remove all windows in secondary display and check that no event happens on window in
    // Remove all windows in secondary display and check that no event happens on window in
    // primary display.
    // primary display.
    mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
    mDispatcher->setInputWindows(
            {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
    windowDefaultDisplay->assertNoEvents();
    windowDefaultDisplay->assertNoEvents();


    // Move cursor position in window in default display and check that only hover move
    // Move cursor position in window in default display and check that only hover move
@@ -2385,8 +2414,9 @@ TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
                                                         .x(400)
                                                         .x(400)
                                                         .y(700))
                                                         .y(700))
                                        .build()));
                                        .build()));
    windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
    windowDefaultDisplay->consumeMotionEvent(
                                       ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
                  WithSource(AINPUT_SOURCE_MOUSE)));
    windowDefaultDisplay->assertNoEvents();
    windowDefaultDisplay->assertNoEvents();
}
}


@@ -4669,6 +4699,7 @@ protected:


        const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
        const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
        assertMotionAction(expectedAction, motionEvent.getAction());
        assertMotionAction(expectedAction, motionEvent.getAction());
        ASSERT_EQ(points.size(), motionEvent.getPointerCount());


        for (size_t i = 0; i < points.size(); i++) {
        for (size_t i = 0; i < points.size(); i++) {
            float expectedX = points[i].x;
            float expectedX = points[i].x;