diff options
author | 2024-06-15 12:58:20 +0000 | |
---|---|---|
committer | 2024-07-08 08:18:05 +0000 | |
commit | 8ff5e5ecde93d80549208f25563f351da90a8dfc (patch) | |
tree | af7f75b07b7828ad83cbcca4269e8e2ac465a27e | |
parent | 9a87716c8a4715332adc8970de44e3f1ea83fb72 (diff) |
Support high-resolution scroll
VirtualMouse currently supports -1f to 1f float scroll values,
but it worked for integer values only as input framework supported
only REL_HWHEEL and REL_WHEEL events. With the introduction of
high-res scroll event support (REL_HWHEEL_HI_RES and REL_WHEEL_HI_RES),
granular mouse scrolling can be done, and VirtualMouse scroll API
would work for all float values.
Flag: android.companion.virtualdevice.flags.high_resolution_scroll
Test: atest VirtualMouseTest
Bug: 335160780
Change-Id: I7b13ac1722b6fd31736fe1c0117d4de6e838261a
-rw-r--r-- | include/input/Input.h | 7 | ||||
-rw-r--r-- | include/input/VirtualInputDevice.h | 2 | ||||
-rw-r--r-- | libs/input/Android.bp | 1 | ||||
-rw-r--r-- | libs/input/VirtualInputDevice.cpp | 48 | ||||
-rw-r--r-- | services/inputflinger/reader/Android.bp | 3 | ||||
-rw-r--r-- | services/inputflinger/reader/mapper/TouchInputMapper.h | 4 | ||||
-rw-r--r-- | services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp | 37 | ||||
-rw-r--r-- | services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h | 11 | ||||
-rw-r--r-- | services/inputflinger/tests/Android.bp | 1 | ||||
-rw-r--r-- | services/inputflinger/tests/CursorInputMapper_test.cpp | 139 | ||||
-rw-r--r-- | services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp | 4 | ||||
-rw-r--r-- | services/inputflinger/tests/TestEventMatchers.h | 9 |
12 files changed, 251 insertions, 15 deletions
diff --git a/include/input/Input.h b/include/input/Input.h index 456977bb34..17672d11f7 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -196,6 +196,13 @@ static constexpr size_t MAX_POINTERS = 16; #define MAX_POINTER_ID 31 /* + * Number of high resolution mouse scroll units for one detent (mouse wheel click), as defined in + * evdev. This is relevant when an input device is emitting REL_WHEEL_HI_RES or REL_HWHEEL_HI_RES + * events. + */ +constexpr int32_t kEvdevMouseHighResScrollUnitsPerDetent = 120; + +/* * Declare a concrete type for the NDK's input event forward declaration. */ struct AInputEvent { diff --git a/include/input/VirtualInputDevice.h b/include/input/VirtualInputDevice.h index 9bbaa0c5ec..9fbae73167 100644 --- a/include/input/VirtualInputDevice.h +++ b/include/input/VirtualInputDevice.h @@ -77,6 +77,8 @@ public: private: static const std::map<int, int> BUTTON_CODE_MAPPING; + int32_t mAccumulatedHighResScrollX; + int32_t mAccumulatedHighResScrollY; }; class VirtualTouchscreen : public VirtualInputDevice { diff --git a/libs/input/Android.bp b/libs/input/Android.bp index c2a7ebb614..45ebc66ddc 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -258,6 +258,7 @@ cc_library { ], shared_libs: [ + "android.companion.virtualdevice.flags-aconfig-cc-host", "libbase", "libbinder", "libbinder_ndk", diff --git a/libs/input/VirtualInputDevice.cpp b/libs/input/VirtualInputDevice.cpp index b73ee65504..2e3e1a09b8 100644 --- a/libs/input/VirtualInputDevice.cpp +++ b/libs/input/VirtualInputDevice.cpp @@ -18,6 +18,7 @@ #include <android/input.h> #include <android/keycodes.h> +#include <android_companion_virtualdevice_flags.h> #include <fcntl.h> #include <input/Input.h> #include <input/VirtualInputDevice.h> @@ -40,6 +41,8 @@ static bool isDebug() { namespace android { +namespace vd_flags = android::companion::virtualdevice::flags; + VirtualInputDevice::VirtualInputDevice(unique_fd fd) : mFd(std::move(fd)) {} VirtualInputDevice::~VirtualInputDevice() { @@ -253,7 +256,10 @@ const std::map<int, int> VirtualMouse::BUTTON_CODE_MAPPING = { // clang-format on }; -VirtualMouse::VirtualMouse(unique_fd fd) : VirtualInputDevice(std::move(fd)) {} +VirtualMouse::VirtualMouse(unique_fd fd) + : VirtualInputDevice(std::move(fd)), + mAccumulatedHighResScrollX(0), + mAccumulatedHighResScrollY(0) {} VirtualMouse::~VirtualMouse() {} @@ -272,9 +278,43 @@ bool VirtualMouse::writeRelativeEvent(float relativeX, float relativeY, bool VirtualMouse::writeScrollEvent(float xAxisMovement, float yAxisMovement, std::chrono::nanoseconds eventTime) { - return writeInputEvent(EV_REL, REL_HWHEEL, xAxisMovement, eventTime) && - writeInputEvent(EV_REL, REL_WHEEL, yAxisMovement, eventTime) && - writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); + if (!vd_flags::high_resolution_scroll()) { + return writeInputEvent(EV_REL, REL_HWHEEL, xAxisMovement, eventTime) && + writeInputEvent(EV_REL, REL_WHEEL, yAxisMovement, eventTime) && + writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); + } + + const int32_t highResScrollX = xAxisMovement * kEvdevMouseHighResScrollUnitsPerDetent; + const int32_t highResScrollY = yAxisMovement * kEvdevMouseHighResScrollUnitsPerDetent; + bool highResScrollResult = + writeInputEvent(EV_REL, REL_HWHEEL_HI_RES, highResScrollX, eventTime) && + writeInputEvent(EV_REL, REL_WHEEL_HI_RES, highResScrollY, eventTime); + if (!highResScrollResult) { + return false; + } + + // According to evdev spec, a high-resolution mouse needs to emit REL_WHEEL / REL_HWHEEL events + // in addition to high-res scroll events. Regular scroll events can approximate high-res scroll + // events, so we send a regular scroll event when the accumulated scroll motion reaches a detent + // (single mouse wheel click). + mAccumulatedHighResScrollX += highResScrollX; + mAccumulatedHighResScrollY += highResScrollY; + const int32_t scrollX = mAccumulatedHighResScrollX / kEvdevMouseHighResScrollUnitsPerDetent; + const int32_t scrollY = mAccumulatedHighResScrollY / kEvdevMouseHighResScrollUnitsPerDetent; + if (scrollX != 0) { + if (!writeInputEvent(EV_REL, REL_HWHEEL, scrollX, eventTime)) { + return false; + } + mAccumulatedHighResScrollX %= kEvdevMouseHighResScrollUnitsPerDetent; + } + if (scrollY != 0) { + if (!writeInputEvent(EV_REL, REL_WHEEL, scrollY, eventTime)) { + return false; + } + mAccumulatedHighResScrollY %= kEvdevMouseHighResScrollUnitsPerDetent; + } + + return writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); } // --- VirtualTouchscreen --- diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index b2f15b400d..a052a4eb83 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -78,7 +78,6 @@ cc_defaults { name: "libinputreader_defaults", srcs: [":libinputreader_sources"], shared_libs: [ - "android.companion.virtualdevice.flags-aconfig-cc-host", "libbase", "libcap", "libcrypto", @@ -116,6 +115,7 @@ cc_library_static { "libinputreader_defaults", ], shared_libs: [ + "android.companion.virtualdevice.flags-aconfig-cc-host", "libinputflinger_base", ], export_header_lib_headers: [ @@ -141,6 +141,7 @@ cc_library_shared { shared_libs: [ // This should consist only of dependencies from inputflinger. Other dependencies should be // in cc_defaults so that they are included in the tests. + "android.companion.virtualdevice.flags-aconfig-cc-host", "libinputflinger_base", "libjsoncpp", ], diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index beab6e7179..87b72afe7c 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -339,8 +339,8 @@ protected: int32_t buttonState{}; // Scroll state. - int32_t rawVScroll{}; - int32_t rawHScroll{}; + float rawVScroll{}; + float rawHScroll{}; inline void clear() { *this = RawState(); } }; diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp index f85cab205b..06315e2259 100644 --- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.cpp @@ -16,18 +16,29 @@ #include "CursorScrollAccumulator.h" +#include <android_companion_virtualdevice_flags.h> #include "EventHub.h" #include "InputDevice.h" namespace android { -CursorScrollAccumulator::CursorScrollAccumulator() : mHaveRelWheel(false), mHaveRelHWheel(false) { +namespace vd_flags = android::companion::virtualdevice::flags; + +CursorScrollAccumulator::CursorScrollAccumulator() + : mHaveRelWheel(false), + mHaveRelHWheel(false), + mHaveRelWheelHighRes(false), + mHaveRelHWheelHighRes(false) { clearRelativeAxes(); } void CursorScrollAccumulator::configure(InputDeviceContext& deviceContext) { mHaveRelWheel = deviceContext.hasRelativeAxis(REL_WHEEL); mHaveRelHWheel = deviceContext.hasRelativeAxis(REL_HWHEEL); + if (vd_flags::high_resolution_scroll()) { + mHaveRelWheelHighRes = deviceContext.hasRelativeAxis(REL_WHEEL_HI_RES); + mHaveRelHWheelHighRes = deviceContext.hasRelativeAxis(REL_HWHEEL_HI_RES); + } } void CursorScrollAccumulator::reset(InputDeviceContext& deviceContext) { @@ -42,11 +53,31 @@ void CursorScrollAccumulator::clearRelativeAxes() { void CursorScrollAccumulator::process(const RawEvent& rawEvent) { if (rawEvent.type == EV_REL) { switch (rawEvent.code) { + case REL_WHEEL_HI_RES: + if (mHaveRelWheelHighRes) { + mRelWheel = rawEvent.value / + static_cast<float>(kEvdevMouseHighResScrollUnitsPerDetent); + } + break; + case REL_HWHEEL_HI_RES: + if (mHaveRelHWheelHighRes) { + mRelHWheel = rawEvent.value / + static_cast<float>(kEvdevMouseHighResScrollUnitsPerDetent); + } + break; case REL_WHEEL: - mRelWheel = rawEvent.value; + // We should ignore regular scroll events, if we have already have high-res scroll + // enabled. + if (!mHaveRelWheelHighRes) { + mRelWheel = rawEvent.value; + } break; case REL_HWHEEL: - mRelHWheel = rawEvent.value; + // We should ignore regular scroll events, if we have already have high-res scroll + // enabled. + if (!mHaveRelHWheelHighRes) { + mRelHWheel = rawEvent.value; + } break; } } diff --git a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h index e563620252..6990d208f9 100644 --- a/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h +++ b/services/inputflinger/reader/mapper/accumulator/CursorScrollAccumulator.h @@ -24,7 +24,6 @@ class InputDeviceContext; struct RawEvent; /* Keeps track of cursor scrolling motions. */ - class CursorScrollAccumulator { public: CursorScrollAccumulator(); @@ -39,17 +38,19 @@ public: inline int32_t getRelativeX() const { return mRelX; } inline int32_t getRelativeY() const { return mRelY; } - inline int32_t getRelativeVWheel() const { return mRelWheel; } - inline int32_t getRelativeHWheel() const { return mRelHWheel; } + inline float getRelativeVWheel() const { return mRelWheel; } + inline float getRelativeHWheel() const { return mRelHWheel; } private: bool mHaveRelWheel; bool mHaveRelHWheel; + bool mHaveRelWheelHighRes; + bool mHaveRelHWheelHighRes; int32_t mRelX; int32_t mRelY; - int32_t mRelWheel; - int32_t mRelHWheel; + float mRelWheel; + float mRelHWheel; void clearRelativeAxes(); }; diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index 189f117897..65e04291a1 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -109,6 +109,7 @@ cc_test { }, }, static_libs: [ + "android.companion.virtualdevice.flags-aconfig-cc-test", "libflagtest", "libgmock", ], diff --git a/services/inputflinger/tests/CursorInputMapper_test.cpp b/services/inputflinger/tests/CursorInputMapper_test.cpp index 83074ff899..727237f287 100644 --- a/services/inputflinger/tests/CursorInputMapper_test.cpp +++ b/services/inputflinger/tests/CursorInputMapper_test.cpp @@ -22,6 +22,7 @@ #include <variant> #include <android-base/logging.h> +#include <android_companion_virtualdevice_flags.h> #include <com_android_input_flags.h> #include <gtest/gtest.h> #include <input/DisplayViewport.h> @@ -127,6 +128,7 @@ private: } // namespace namespace input_flags = com::android::input::flags; +namespace vd_flags = android::companion::virtualdevice::flags; /** * Unit tests for CursorInputMapper. @@ -151,6 +153,10 @@ protected: .WillRepeatedly(Return(false)); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL)) .WillRepeatedly(Return(false)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES)) + .WillRepeatedly(Return(false)); mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID); mFakePolicy->addDisplayViewport(createPrimaryViewport(ui::Rotation::Rotation0)); @@ -194,6 +200,7 @@ class CursorInputMapperUnitTest : public CursorInputMapperUnitTestBase { protected: void SetUp() override { input_flags::enable_new_mouse_pointer_ballistics(false); + vd_flags::high_resolution_scroll(false); CursorInputMapperUnitTestBase::SetUp(); } }; @@ -840,6 +847,72 @@ TEST_F(CursorInputMapperUnitTest, ProcessWhenModeIsPointerShouldKeepZeroCoords) WithOrientation(0.0f), WithDistance(0.0f))))); } +TEST_F(CursorInputMapperUnitTest, ProcessRegularScroll) { + createMapper(); + + std::list<NotifyArgs> args; + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1); + args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + EXPECT_THAT(args, + ElementsAre(VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), + VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), + WithScroll(1.0f, 1.0f))))); +} + +TEST_F(CursorInputMapperUnitTest, ProcessHighResScroll) { + vd_flags::high_resolution_scroll(true); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES)) + .WillRepeatedly(Return(true)); + createMapper(); + + std::list<NotifyArgs> args; + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60); + args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + EXPECT_THAT(args, + ElementsAre(VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), + VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), + WithScroll(0.5f, 0.5f))))); +} + +TEST_F(CursorInputMapperUnitTest, HighResScrollIgnoresRegularScroll) { + vd_flags::high_resolution_scroll(true); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES)) + .WillRepeatedly(Return(true)); + createMapper(); + + std::list<NotifyArgs> args; + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60); + args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60); + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1); + args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + EXPECT_THAT(args, + ElementsAre(VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), + VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), + WithScroll(0.5f, 0.5f))))); +} + /** * When Pointer Capture is enabled, we expect to report unprocessed relative movements, so any * pointer acceleration or speed processing should not be applied. @@ -1030,6 +1103,72 @@ TEST_F(CursorInputMapperUnitTestWithNewBallistics, ConfigureAccelerationOnDispla WithRelativeMotion(10, 20))))); } +TEST_F(CursorInputMapperUnitTestWithNewBallistics, ProcessRegularScroll) { + createMapper(); + + std::list<NotifyArgs> args; + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1); + args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + EXPECT_THAT(args, + ElementsAre(VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), + VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), + WithScroll(1.0f, 1.0f))))); +} + +TEST_F(CursorInputMapperUnitTestWithNewBallistics, ProcessHighResScroll) { + vd_flags::high_resolution_scroll(true); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES)) + .WillRepeatedly(Return(true)); + createMapper(); + + std::list<NotifyArgs> args; + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60); + args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + EXPECT_THAT(args, + ElementsAre(VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), + VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), + WithScroll(0.5f, 0.5f))))); +} + +TEST_F(CursorInputMapperUnitTestWithNewBallistics, HighResScrollIgnoresRegularScroll) { + vd_flags::high_resolution_scroll(true); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES)) + .WillRepeatedly(Return(true)); + createMapper(); + + std::list<NotifyArgs> args; + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60); + args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60); + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1); + args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + EXPECT_THAT(args, + ElementsAre(VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))), + VariantWith<NotifyMotionArgs>( + AllOf(WithSource(AINPUT_SOURCE_MOUSE), + WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), + WithScroll(0.5f, 0.5f))))); +} + namespace { // Minimum timestamp separation between subsequent input events from a Bluetooth device. diff --git a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp index 94cfc3274b..2b8071bd88 100644 --- a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp +++ b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp @@ -122,6 +122,10 @@ protected: .WillRepeatedly(Return(true)); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL)) .WillRepeatedly(Return(false)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES)) + .WillRepeatedly(Return(false)); } }; diff --git a/services/inputflinger/tests/TestEventMatchers.h b/services/inputflinger/tests/TestEventMatchers.h index 65fb9c6659..f643fb11e5 100644 --- a/services/inputflinger/tests/TestEventMatchers.h +++ b/services/inputflinger/tests/TestEventMatchers.h @@ -697,6 +697,15 @@ MATCHER_P(WithDistance, distance, "MotionEvent with specified distance") { return argDistance == distance; } +MATCHER_P2(WithScroll, scrollX, scrollY, "InputEvent with specified scroll values") { + const auto argScrollX = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_HSCROLL); + const auto argScrollY = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_VSCROLL); + *result_listener << "expected scroll values " << scrollX << " scroll x " << scrollY + << " scroll y, but got " << argScrollX << " scroll x " << argScrollY + << " scroll y"; + return argScrollX == scrollX && argScrollY == scrollY; +} + MATCHER_P2(WithTouchDimensions, maj, min, "InputEvent with specified touch dimensions") { const auto argMajor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR); const auto argMinor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR); |