Loading include/input/Input.h +13 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,19 @@ enum class ToolType { ftl_last = PALM, }; /** * The state of the key. This should have 1:1 correspondence with the values of anonymous enum * defined in input.h */ enum class KeyState { UNKNOWN = AKEY_STATE_UNKNOWN, UP = AKEY_STATE_UP, DOWN = AKEY_STATE_DOWN, VIRTUAL = AKEY_STATE_VIRTUAL, ftl_first = UNKNOWN, ftl_last = VIRTUAL, }; bool isStylusToolType(ToolType toolType); /* Loading services/inputflinger/tests/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ cc_test { "AnrTracker_test.cpp", "BlockingQueue_test.cpp", "CapturedTouchpadEventConverter_test.cpp", "CursorInputMapper_test.cpp", "EventHub_test.cpp", "FakeEventHub.cpp", "FakeInputReaderPolicy.cpp", Loading @@ -58,6 +59,7 @@ cc_test { "PreferStylusOverTouch_test.cpp", "PropertyProvider_test.cpp", "TestInputListener.cpp", "TouchpadInputMapper_test.cpp", "UinputDevice.cpp", "UnwantedInteractionBlocker_test.cpp", ], Loading services/inputflinger/tests/CursorInputMapper_test.cpp 0 → 100644 +105 −0 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "CursorInputMapper.h" #include <android-base/logging.h> #include <gtest/gtest.h> #include "FakePointerController.h" #include "InputMapperTest.h" #include "InterfaceMocks.h" #include "TestInputListenerMatchers.h" #define TAG "CursorInputMapper_test" namespace android { using testing::Return; using testing::VariantWith; constexpr auto ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN; constexpr auto ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE; constexpr auto ACTION_UP = AMOTION_EVENT_ACTION_UP; constexpr auto BUTTON_PRESS = AMOTION_EVENT_ACTION_BUTTON_PRESS; constexpr auto BUTTON_RELEASE = AMOTION_EVENT_ACTION_BUTTON_RELEASE; constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE; /** * Unit tests for CursorInputMapper. * This class is named 'CursorInputMapperUnitTest' to avoid name collision with the existing * 'CursorInputMapperTest'. If all of the CursorInputMapper tests are migrated here, the name * can be simplified to 'CursorInputMapperTest'. * TODO(b/283812079): move CursorInputMapper tests here. */ class CursorInputMapperUnitTest : public InputMapperUnitTest { protected: void SetUp() override { InputMapperUnitTest::SetUp(); // Current scan code state - all keys are UP by default setScanCodeState(KeyState::UP, {BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, BTN_BACK, BTN_SIDE, BTN_FORWARD, BTN_EXTRA, BTN_TASK}); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL)) .WillRepeatedly(Return(false)); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL)) .WillRepeatedly(Return(false)); EXPECT_CALL(mMockInputReaderContext, bumpGeneration()).WillRepeatedly(Return(1)); mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration); } }; /** * Move the mouse and then click the button. Check whether HOVER_EXIT is generated when hovering * ends. Currently, it is not. */ TEST_F(CursorInputMapperUnitTest, HoverAndLeftButtonPress) { std::list<NotifyArgs> args; // Move the cursor a little args += process(EV_REL, REL_X, 10); args += process(EV_REL, REL_Y, 20); args += process(EV_SYN, SYN_REPORT, 0); ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)))); // Now click the mouse button args.clear(); args += process(EV_KEY, BTN_LEFT, 1); args += process(EV_SYN, SYN_REPORT, 0); ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)), VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS)))); // Move some more. args.clear(); args += process(EV_REL, REL_X, 10); args += process(EV_REL, REL_Y, 20); args += process(EV_SYN, SYN_REPORT, 0); ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_MOVE)))); // Release the button args.clear(); args += process(EV_KEY, BTN_LEFT, 0); args += process(EV_SYN, SYN_REPORT, 0); ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)), VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)), VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)))); } } // namespace android services/inputflinger/tests/InputMapperTest.cpp +68 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,74 @@ namespace android { using testing::Return; void InputMapperUnitTest::SetUp() { mFakePointerController = std::make_shared<FakePointerController>(); mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1); mFakePointerController->setPosition(400, 240); EXPECT_CALL(mMockInputReaderContext, getPointerController(DEVICE_ID)) .WillRepeatedly(Return(mFakePointerController)); EXPECT_CALL(mMockInputReaderContext, getEventHub()).WillRepeatedly(Return(&mMockEventHub)); InputDeviceIdentifier identifier; identifier.name = "device"; identifier.location = "USB1"; identifier.bus = 0; EXPECT_CALL(mMockEventHub, getDeviceIdentifier(EVENTHUB_ID)).WillRepeatedly(Return(identifier)); mDevice = std::make_unique<InputDevice>(&mMockInputReaderContext, DEVICE_ID, /*generation=*/2, identifier); mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID); } void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution) { EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, testing::_)) .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) { outAxisInfo->valid = valid; outAxisInfo->minValue = min; outAxisInfo->maxValue = max; outAxisInfo->flat = 0; outAxisInfo->fuzz = 0; outAxisInfo->resolution = resolution; return valid ? OK : -1; }); } void InputMapperUnitTest::expectScanCodes(bool present, std::set<int> scanCodes) { for (const auto& scanCode : scanCodes) { EXPECT_CALL(mMockEventHub, hasScanCode(EVENTHUB_ID, scanCode)) .WillRepeatedly(testing::Return(present)); } } void InputMapperUnitTest::setScanCodeState(KeyState state, std::set<int> scanCodes) { for (const auto& scanCode : scanCodes) { EXPECT_CALL(mMockEventHub, getScanCodeState(EVENTHUB_ID, scanCode)) .WillRepeatedly(testing::Return(static_cast<int>(state))); } } void InputMapperUnitTest::setKeyCodeState(KeyState state, std::set<int> keyCodes) { for (const auto& keyCode : keyCodes) { EXPECT_CALL(mMockEventHub, getKeyCodeState(EVENTHUB_ID, keyCode)) .WillRepeatedly(testing::Return(static_cast<int>(state))); } } std::list<NotifyArgs> InputMapperUnitTest::process(int32_t type, int32_t code, int32_t value) { RawEvent event; event.when = systemTime(SYSTEM_TIME_MONOTONIC); event.readTime = event.when; event.deviceId = mMapper->getDeviceContext().getEventHubId(); event.type = type; event.code = code; event.value = value; return mMapper->process(&event); } const char* InputMapperTest::DEVICE_NAME = "device"; const char* InputMapperTest::DEVICE_LOCATION = "USB1"; const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES = Loading services/inputflinger/tests/InputMapperTest.h +32 −0 Original line number Diff line number Diff line Loading @@ -23,16 +23,48 @@ #include <InputMapper.h> #include <NotifyArgs.h> #include <ftl/flags.h> #include <gmock/gmock.h> #include <utils/StrongPointer.h> #include "FakeEventHub.h" #include "FakeInputReaderPolicy.h" #include "InstrumentedInputReader.h" #include "InterfaceMocks.h" #include "TestConstants.h" #include "TestInputListener.h" namespace android { class InputMapperUnitTest : public testing::Test { protected: static constexpr int32_t EVENTHUB_ID = 1; static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000; virtual void SetUp() override; void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution); void expectScanCodes(bool present, std::set<int> scanCodes); void setScanCodeState(KeyState state, std::set<int> scanCodes); void setKeyCodeState(KeyState state, std::set<int> keyCodes); std::list<NotifyArgs> process(int32_t type, int32_t code, int32_t value); MockEventHubInterface mMockEventHub; std::shared_ptr<FakePointerController> mFakePointerController; MockInputReaderContext mMockInputReaderContext; std::unique_ptr<InputDevice> mDevice; std::unique_ptr<InputDeviceContext> mDeviceContext; InputReaderConfiguration mReaderConfiguration; // The mapper should be created by the subclasses. std::unique_ptr<InputMapper> mMapper; }; /** * Deprecated - use InputMapperUnitTest instead. */ class InputMapperTest : public testing::Test { protected: static const char* DEVICE_NAME; Loading Loading
include/input/Input.h +13 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,19 @@ enum class ToolType { ftl_last = PALM, }; /** * The state of the key. This should have 1:1 correspondence with the values of anonymous enum * defined in input.h */ enum class KeyState { UNKNOWN = AKEY_STATE_UNKNOWN, UP = AKEY_STATE_UP, DOWN = AKEY_STATE_DOWN, VIRTUAL = AKEY_STATE_VIRTUAL, ftl_first = UNKNOWN, ftl_last = VIRTUAL, }; bool isStylusToolType(ToolType toolType); /* Loading
services/inputflinger/tests/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ cc_test { "AnrTracker_test.cpp", "BlockingQueue_test.cpp", "CapturedTouchpadEventConverter_test.cpp", "CursorInputMapper_test.cpp", "EventHub_test.cpp", "FakeEventHub.cpp", "FakeInputReaderPolicy.cpp", Loading @@ -58,6 +59,7 @@ cc_test { "PreferStylusOverTouch_test.cpp", "PropertyProvider_test.cpp", "TestInputListener.cpp", "TouchpadInputMapper_test.cpp", "UinputDevice.cpp", "UnwantedInteractionBlocker_test.cpp", ], Loading
services/inputflinger/tests/CursorInputMapper_test.cpp 0 → 100644 +105 −0 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "CursorInputMapper.h" #include <android-base/logging.h> #include <gtest/gtest.h> #include "FakePointerController.h" #include "InputMapperTest.h" #include "InterfaceMocks.h" #include "TestInputListenerMatchers.h" #define TAG "CursorInputMapper_test" namespace android { using testing::Return; using testing::VariantWith; constexpr auto ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN; constexpr auto ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE; constexpr auto ACTION_UP = AMOTION_EVENT_ACTION_UP; constexpr auto BUTTON_PRESS = AMOTION_EVENT_ACTION_BUTTON_PRESS; constexpr auto BUTTON_RELEASE = AMOTION_EVENT_ACTION_BUTTON_RELEASE; constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE; /** * Unit tests for CursorInputMapper. * This class is named 'CursorInputMapperUnitTest' to avoid name collision with the existing * 'CursorInputMapperTest'. If all of the CursorInputMapper tests are migrated here, the name * can be simplified to 'CursorInputMapperTest'. * TODO(b/283812079): move CursorInputMapper tests here. */ class CursorInputMapperUnitTest : public InputMapperUnitTest { protected: void SetUp() override { InputMapperUnitTest::SetUp(); // Current scan code state - all keys are UP by default setScanCodeState(KeyState::UP, {BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, BTN_BACK, BTN_SIDE, BTN_FORWARD, BTN_EXTRA, BTN_TASK}); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL)) .WillRepeatedly(Return(false)); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL)) .WillRepeatedly(Return(false)); EXPECT_CALL(mMockInputReaderContext, bumpGeneration()).WillRepeatedly(Return(1)); mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration); } }; /** * Move the mouse and then click the button. Check whether HOVER_EXIT is generated when hovering * ends. Currently, it is not. */ TEST_F(CursorInputMapperUnitTest, HoverAndLeftButtonPress) { std::list<NotifyArgs> args; // Move the cursor a little args += process(EV_REL, REL_X, 10); args += process(EV_REL, REL_Y, 20); args += process(EV_SYN, SYN_REPORT, 0); ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)))); // Now click the mouse button args.clear(); args += process(EV_KEY, BTN_LEFT, 1); args += process(EV_SYN, SYN_REPORT, 0); ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)), VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS)))); // Move some more. args.clear(); args += process(EV_REL, REL_X, 10); args += process(EV_REL, REL_Y, 20); args += process(EV_SYN, SYN_REPORT, 0); ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_MOVE)))); // Release the button args.clear(); args += process(EV_KEY, BTN_LEFT, 0); args += process(EV_SYN, SYN_REPORT, 0); ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)), VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)), VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)))); } } // namespace android
services/inputflinger/tests/InputMapperTest.cpp +68 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,74 @@ namespace android { using testing::Return; void InputMapperUnitTest::SetUp() { mFakePointerController = std::make_shared<FakePointerController>(); mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1); mFakePointerController->setPosition(400, 240); EXPECT_CALL(mMockInputReaderContext, getPointerController(DEVICE_ID)) .WillRepeatedly(Return(mFakePointerController)); EXPECT_CALL(mMockInputReaderContext, getEventHub()).WillRepeatedly(Return(&mMockEventHub)); InputDeviceIdentifier identifier; identifier.name = "device"; identifier.location = "USB1"; identifier.bus = 0; EXPECT_CALL(mMockEventHub, getDeviceIdentifier(EVENTHUB_ID)).WillRepeatedly(Return(identifier)); mDevice = std::make_unique<InputDevice>(&mMockInputReaderContext, DEVICE_ID, /*generation=*/2, identifier); mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID); } void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution) { EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, testing::_)) .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) { outAxisInfo->valid = valid; outAxisInfo->minValue = min; outAxisInfo->maxValue = max; outAxisInfo->flat = 0; outAxisInfo->fuzz = 0; outAxisInfo->resolution = resolution; return valid ? OK : -1; }); } void InputMapperUnitTest::expectScanCodes(bool present, std::set<int> scanCodes) { for (const auto& scanCode : scanCodes) { EXPECT_CALL(mMockEventHub, hasScanCode(EVENTHUB_ID, scanCode)) .WillRepeatedly(testing::Return(present)); } } void InputMapperUnitTest::setScanCodeState(KeyState state, std::set<int> scanCodes) { for (const auto& scanCode : scanCodes) { EXPECT_CALL(mMockEventHub, getScanCodeState(EVENTHUB_ID, scanCode)) .WillRepeatedly(testing::Return(static_cast<int>(state))); } } void InputMapperUnitTest::setKeyCodeState(KeyState state, std::set<int> keyCodes) { for (const auto& keyCode : keyCodes) { EXPECT_CALL(mMockEventHub, getKeyCodeState(EVENTHUB_ID, keyCode)) .WillRepeatedly(testing::Return(static_cast<int>(state))); } } std::list<NotifyArgs> InputMapperUnitTest::process(int32_t type, int32_t code, int32_t value) { RawEvent event; event.when = systemTime(SYSTEM_TIME_MONOTONIC); event.readTime = event.when; event.deviceId = mMapper->getDeviceContext().getEventHubId(); event.type = type; event.code = code; event.value = value; return mMapper->process(&event); } const char* InputMapperTest::DEVICE_NAME = "device"; const char* InputMapperTest::DEVICE_LOCATION = "USB1"; const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES = Loading
services/inputflinger/tests/InputMapperTest.h +32 −0 Original line number Diff line number Diff line Loading @@ -23,16 +23,48 @@ #include <InputMapper.h> #include <NotifyArgs.h> #include <ftl/flags.h> #include <gmock/gmock.h> #include <utils/StrongPointer.h> #include "FakeEventHub.h" #include "FakeInputReaderPolicy.h" #include "InstrumentedInputReader.h" #include "InterfaceMocks.h" #include "TestConstants.h" #include "TestInputListener.h" namespace android { class InputMapperUnitTest : public testing::Test { protected: static constexpr int32_t EVENTHUB_ID = 1; static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000; virtual void SetUp() override; void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution); void expectScanCodes(bool present, std::set<int> scanCodes); void setScanCodeState(KeyState state, std::set<int> scanCodes); void setKeyCodeState(KeyState state, std::set<int> keyCodes); std::list<NotifyArgs> process(int32_t type, int32_t code, int32_t value); MockEventHubInterface mMockEventHub; std::shared_ptr<FakePointerController> mFakePointerController; MockInputReaderContext mMockInputReaderContext; std::unique_ptr<InputDevice> mDevice; std::unique_ptr<InputDeviceContext> mDeviceContext; InputReaderConfiguration mReaderConfiguration; // The mapper should be created by the subclasses. std::unique_ptr<InputMapper> mMapper; }; /** * Deprecated - use InputMapperUnitTest instead. */ class InputMapperTest : public testing::Test { protected: static const char* DEVICE_NAME; Loading