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

Commit c6f2a4f8 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou Committed by Android (Google) Code Review
Browse files

Merge "Erase touch state if empty"

parents 4cff8d5f 0b0374d3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
          "include-filter": "android.view.cts.input",
          "include-filter": "android.view.cts.MotionEventTest",
          "include-filter": "android.view.cts.PointerCaptureTest",
          "include-filter": "android.view.cts.TooltipTest",
          "include-filter": "android.view.cts.VerifyInputEventTest"
        }
      ]
@@ -128,6 +129,7 @@
        {
          "include-filter": "android.view.cts.MotionEventTest",
          "include-filter": "android.view.cts.PointerCaptureTest",
          "include-filter": "android.view.cts.TooltipTest",
          "include-filter": "android.view.cts.VerifyInputEventTest"
        }
      ]
+10 −5
Original line number Diff line number Diff line
@@ -1769,15 +1769,16 @@ void InputDispatcher::dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<Dr

void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry& entry) {
    if (DEBUG_OUTBOUND_EVENT_DETAILS) {
        ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
        ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=%s, displayId=%" PRId32
              ", policyFlags=0x%x, "
              "action=%s, actionButton=0x%x, flags=0x%x, "
              "metaState=0x%x, buttonState=0x%x,"
              "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
              prefix, entry.eventTime, entry.deviceId, entry.source, entry.displayId,
              entry.policyFlags, MotionEvent::actionToString(entry.action).c_str(),
              entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.edgeFlags,
              entry.xPrecision, entry.yPrecision, entry.downTime);
              prefix, entry.eventTime, entry.deviceId,
              inputEventSourceToString(entry.source).c_str(), entry.displayId, entry.policyFlags,
              MotionEvent::actionToString(entry.action).c_str(), entry.actionButton, entry.flags,
              entry.metaState, entry.buttonState, entry.edgeFlags, entry.xPrecision,
              entry.yPrecision, entry.downTime);

        for (uint32_t i = 0; i < entry.pointerCount; i++) {
            ALOGD("  Pointer %d: id=%d, toolType=%d, "
@@ -2502,6 +2503,10 @@ Failed:
        }
    }

    if (tempTouchState.windows.empty()) {
        mTouchStatesByDisplay.erase(displayId);
    }

    // Update hover state.
    mLastHoverWindowHandle = newHoverWindowHandle;

+2 −1
Original line number Diff line number Diff line
@@ -148,7 +148,8 @@ bool TouchState::isDown() const {

std::string TouchState::dump() const {
    std::string out;
    out += StringPrintf("deviceId=%d, source=0x%08x\n", deviceId, source);
    out += StringPrintf("deviceId=%d, source=%s\n", deviceId,
                        inputEventSourceToString(source).c_str());
    if (!windows.empty()) {
        out += "  Windows:\n";
        for (size_t i = 0; i < windows.size(); i++) {
+72 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <android-base/thread_annotations.h>
#include <binder/Binder.h>
#include <fcntl.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <input/Input.h>
#include <linux/input.h>
@@ -43,6 +44,7 @@ using android::os::InputEventInjectionSync;
namespace android::inputdispatcher {

using namespace ftl::flag_operators;
using testing::AllOf;

// An arbitrary time value.
static constexpr nsecs_t ARBITRARY_TIME = 1234;
@@ -102,6 +104,28 @@ static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
            << MotionEvent::actionToString(receivedAction);
}

MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
    bool matches = action == arg.getAction();
    if (!matches) {
        *result_listener << "expected action " << MotionEvent::actionToString(action)
                         << ", but got " << MotionEvent::actionToString(arg.getAction());
    }
    if (action == AMOTION_EVENT_ACTION_CANCEL) {
        if (!matches) {
            *result_listener << "; ";
        }
        *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
        matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
    }
    return matches;
}

MATCHER_P(WithSource, source, "InputEvent with specified source") {
    *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
                     << inputEventSourceToString(arg.getSource());
    return arg.getSource() == source;
}

// --- FakeInputDispatcherPolicy ---

class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
@@ -1205,6 +1229,12 @@ public:
        mInputReceiver->consumeCaptureEvent(hasCapture);
    }

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

    void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
                      std::optional<int32_t> expectedDisplayId,
                      std::optional<int32_t> expectedFlags) {
@@ -2207,6 +2237,48 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
                         ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
}

/**
 * Inject a mouse hover event followed by a tap from touchscreen.
 * In the current implementation, the tap does not cause a HOVER_EXIT event.
 */
TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
    window->setFrame(Rect(0, 0, 100, 100));

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

    // Inject a hover_move from mouse.
    NotifyMotionArgs motionArgs =
            generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
                               ADISPLAY_ID_DEFAULT, {{50, 50}});
    motionArgs.xCursorPosition = 50;
    motionArgs.yCursorPosition = 50;
    mDispatcher->notifyMotion(&motionArgs);
    ASSERT_NO_FATAL_FAILURE(
            window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
                                             WithSource(AINPUT_SOURCE_MOUSE))));
    ASSERT_NO_FATAL_FAILURE(
            window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
                                             WithSource(AINPUT_SOURCE_MOUSE))));

    // Tap on the window
    motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
                                    ADISPLAY_ID_DEFAULT, {{10, 10}});
    mDispatcher->notifyMotion(&motionArgs);
    ASSERT_NO_FATAL_FAILURE(
            window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
                                             WithSource(AINPUT_SOURCE_TOUCHSCREEN))));

    motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
                                    ADISPLAY_ID_DEFAULT, {{10, 10}});
    mDispatcher->notifyMotion(&motionArgs);
    ASSERT_NO_FATAL_FAILURE(
            window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
                                             WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
}

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

+2 −1
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@ MATCHER_P(WithKeyAction, action, "KeyEvent with specified action") {
}

MATCHER_P(WithSource, source, "InputEvent with specified source") {
    *result_listener << "expected source " << source << ", but got " << arg.source;
    *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
                     << inputEventSourceToString(arg.source);
    return arg.source == source;
}