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

Commit 5893d364 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Add test case for hover eventId synthesis

When a new event is synthesized in InputDispatcher causing its action to
change, the synthesized event should always have a new eventId. Verify
this by adding a test case where hover enters and exits are synthesized
from hover moves, and ensure the synthesized events have a new eventId,
while move events retain their original id.

Bug: 210460522
Test: atest inputflinger_tests
Change-Id: Icb413f412dd68a0e6bfb056af18ef5e0935facef
parent 2a2da1d8
Loading
Loading
Loading
Loading
+57 −3
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "TestEventMatchers.h"
#include <NotifyArgsBuilders.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/silent_death_test.h>
#include <android-base/stringprintf.h>
@@ -53,6 +54,7 @@ namespace android::inputdispatcher {
using namespace ftl::flag_operators;
using testing::AllOf;
using testing::Not;
namespace {
@@ -1319,10 +1321,13 @@ public:
        mInputReceiver->consumeCaptureEvent(hasCapture);
    }
    void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
    const MotionEvent& consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
        MotionEvent* motionEvent = consumeMotion();
        ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
        ASSERT_THAT(*motionEvent, matcher);
        if (nullptr == motionEvent) {
            LOG(FATAL) << "Did not get a motion event, but expected " << matcher;
        }
        EXPECT_THAT(*motionEvent, matcher);
        return *motionEvent;
    }
    void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
@@ -6539,6 +6544,55 @@ TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
    ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
}
TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
                                                           ADISPLAY_ID_DEFAULT);
    left->setFrame(Rect(0, 0, 100, 100));
    sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
                                                            "Right Window", ADISPLAY_ID_DEFAULT);
    right->setFrame(Rect(100, 0, 200, 100));
    sp<FakeWindowHandle> spy =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
    spy->setFrame(Rect(0, 0, 200, 100));
    spy->setTrustedOverlay(true);
    spy->setSpy(true);
    mDispatcher->onWindowInfosChanged(
            {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
    // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
    NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
                                                     ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
    mDispatcher->notifyMotion(notifyArgs);
    const MotionEvent& leftEnter = left->consumeMotionEvent(
            AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
                  WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
    spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
                                  Not(WithEventId(notifyArgs.id)),
                                  Not(WithEventId(leftEnter.getId())),
                                  WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
    // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
    notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
                                    {PointF{150, 50}});
    mDispatcher->notifyMotion(notifyArgs);
    const MotionEvent& leftExit = left->consumeMotionEvent(
            AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
                  WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
    right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
                                    Not(WithEventId(notifyArgs.id)),
                                    Not(WithEventId(leftExit.getId())),
                                    WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
    spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
}
class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
protected:
    std::shared_ptr<FakeApplicationHandle> mApp;
+65 −0
Original line number Diff line number Diff line
@@ -492,6 +492,71 @@ inline WithKeyCodeMatcher WithKeyCode(int32_t keyCode) {
    return WithKeyCodeMatcher(keyCode);
}

/// EventId
class WithEventIdMatcher {
public:
    using is_gtest_matcher = void;
    explicit WithEventIdMatcher(int32_t eventId) : mEventId(eventId) {}

    bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
        return mEventId == args.id;
    }

    bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
        return mEventId == args.id;
    }

    bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
        return mEventId == event.getId();
    }

    void DescribeTo(std::ostream* os) const { *os << "with eventId 0x" << std::hex << mEventId; }

    void DescribeNegationTo(std::ostream* os) const {
        *os << "with eventId not equal to 0x" << std::hex << mEventId;
    }

private:
    const int32_t mEventId;
};

inline WithEventIdMatcher WithEventId(int32_t eventId) {
    return WithEventIdMatcher(eventId);
}

/// EventIdSource
class WithEventIdSourceMatcher {
public:
    using is_gtest_matcher = void;
    explicit WithEventIdSourceMatcher(IdGenerator::Source eventIdSource)
          : mEventIdSource(eventIdSource) {}

    bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
        return mEventIdSource == IdGenerator::getSource(args.id);
    }

    bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
        return mEventIdSource == IdGenerator::getSource(args.id);
    }

    bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
        return mEventIdSource == IdGenerator::getSource(event.getId());
    }

    void DescribeTo(std::ostream* os) const {
        *os << "with eventId from source 0x" << std::hex << ftl::to_underlying(mEventIdSource);
    }

    void DescribeNegationTo(std::ostream* os) const { *os << "wrong event from source"; }

private:
    const IdGenerator::Source mEventIdSource;
};

inline WithEventIdSourceMatcher WithEventIdSource(IdGenerator::Source eventIdSource) {
    return WithEventIdSourceMatcher(eventIdSource);
}

MATCHER_P(WithRepeatCount, repeatCount, "KeyEvent with specified repeat count") {
    return arg.getRepeatCount() == repeatCount;
}