diff options
author | 2024-07-24 21:19:08 +0000 | |
---|---|---|
committer | 2024-07-25 14:13:04 +0000 | |
commit | 31d05c4c78e7924e4bb6dc45092e612a9c7d5bfb (patch) | |
tree | c5d1dd9e1f7189534f1944ed0d29bebe60afd7b7 | |
parent | d2dfdc6123ffcc98c78073c633567c6f22f8d7c2 (diff) |
Mock InputDevice in the InputMapper unit tests
This makes the InputMapperUnitTest subclasses easier to test, as the
tests will not have to rely on the behavior of actual InputDevice
implementation.
Unfortunately, this means InputDevice must now be a virtual class to
allow its mocked subclass to define its behavior for the methods that we
want to change. In this CL, we take the approach of only marking the
methods that we need to customize as virtual to avoid the overhead of
vtable lookups at runtime.
An alternative approach would be to introduce a type parameter to
InputDeviceContext to allow us to specify a different InputDevice
implementation in the tests. This would eliminate any addtional runtime
overheads resulting from vtable lookups. However, this would mean every
InputMapper class would need to have this new type parameter, adding
verbosity and complextity to the codebase. For this reason, the virtual
member approach was preferred.
Bug: 354270482
Test: atest inputflinger_tests
Flag: EXEMPT refactor
Change-Id: Id7e103e1f04812c92ee8ecfdfe1e75a9949efa9e
12 files changed, 84 insertions, 42 deletions
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 086c26f5e2..5eb1accfbf 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -43,7 +43,7 @@ class InputDevice { public: InputDevice(InputReaderContext* context, int32_t id, int32_t generation, const InputDeviceIdentifier& identifier); - ~InputDevice(); + virtual ~InputDevice(); inline InputReaderContext* getContext() { return mContext; } inline int32_t getId() const { return mId; } @@ -56,7 +56,7 @@ public: } inline const std::string getLocation() const { return mIdentifier.location; } inline ftl::Flags<InputDeviceClass> getClasses() const { return mClasses; } - inline uint32_t getSources() const { return mSources; } + inline virtual uint32_t getSources() const { return mSources; } inline bool hasEventHubDevices() const { return !mDevices.empty(); } inline bool isExternal() { return mIsExternal; } @@ -132,7 +132,7 @@ public: [[nodiscard]] NotifyDeviceResetArgs notifyReset(nsecs_t when); - inline const PropertyMap& getConfiguration() { return mConfiguration; } + inline virtual const PropertyMap& getConfiguration() const { return mConfiguration; } inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } std::optional<ui::LogicalDisplayId> getAssociatedDisplayId(); diff --git a/services/inputflinger/tests/CursorInputMapper_test.cpp b/services/inputflinger/tests/CursorInputMapper_test.cpp index 727237f287..846eced2ab 100644 --- a/services/inputflinger/tests/CursorInputMapper_test.cpp +++ b/services/inputflinger/tests/CursorInputMapper_test.cpp @@ -163,7 +163,6 @@ protected: } void createMapper() { - createDevice(); mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration); } @@ -542,7 +541,6 @@ TEST_F(CursorInputMapperUnitTest, ProcessShouldNotRotateMotionsWhenOrientationAw // need to be rotated. mPropertyMap.addProperty("cursor.mode", "navigation"); mPropertyMap.addProperty("cursor.orientationAware", "1"); - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, ui::Rotation::Rotation90); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -560,7 +558,6 @@ TEST_F(CursorInputMapperUnitTest, ProcessShouldRotateMotionsWhenNotOrientationAw // Since InputReader works in the un-rotated coordinate space, only devices that are not // orientation-aware are affected by display rotation. mPropertyMap.addProperty("cursor.mode", "navigation"); - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, ui::Rotation::Rotation0); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -652,7 +649,6 @@ TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdWithAssociatedViewport) { mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport}); // Set up the secondary display as the display on which the pointer should be shown. // The InputDevice is not associated with any display. - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -673,7 +669,6 @@ TEST_F(CursorInputMapperUnitTest, DisplayViewport secondaryViewport = createSecondaryViewport(); mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport}); // Set up the primary display as the display on which the pointer should be shown. - createDevice(); // Associate the InputDevice with the secondary display. ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -1032,7 +1027,6 @@ TEST_F(CursorInputMapperUnitTestWithNewBallistics, ConfigureAccelerationWithAsso mPropertyMap.addProperty("cursor.mode", "pointer"); DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation0); mReaderConfiguration.setDisplayViewports({primaryViewport}); - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, primaryViewport); mMapper = createInputMapper<CursorInputMapper>(deviceContext, mReaderConfiguration); @@ -1070,7 +1064,6 @@ TEST_F(CursorInputMapperUnitTestWithNewBallistics, ConfigureAccelerationOnDispla mReaderConfiguration.setDisplayViewports({primaryViewport}); // Disable acceleration for the display. mReaderConfiguration.displaysWithMousePointerAccelerationDisabled.emplace(DISPLAY_ID); - createDevice(); // Don't associate the device with the display yet. ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp index 7e96d5f5d7..af1f377287 100644 --- a/services/inputflinger/tests/InputMapperTest.cpp +++ b/services/inputflinger/tests/InputMapperTest.cpp @@ -26,7 +26,9 @@ namespace android { using testing::_; +using testing::NiceMock; using testing::Return; +using testing::ReturnRef; void InputMapperUnitTest::SetUpWithBus(int bus) { mFakePolicy = sp<FakeInputReaderPolicy>::make(); @@ -43,16 +45,11 @@ void InputMapperUnitTest::SetUpWithBus(int bus) { EXPECT_CALL(mMockEventHub, getConfiguration(EVENTHUB_ID)).WillRepeatedly([&](int32_t) { return mPropertyMap; }); -} -void InputMapperUnitTest::createDevice() { - mDevice = std::make_unique<InputDevice>(&mMockInputReaderContext, DEVICE_ID, - /*generation=*/2, mIdentifier); - mDevice->addEmptyEventHubDevice(EVENTHUB_ID); + mDevice = std::make_unique<NiceMock<MockInputDevice>>(&mMockInputReaderContext, DEVICE_ID, + /*generation=*/2, mIdentifier); + ON_CALL((*mDevice), getConfiguration).WillByDefault(ReturnRef(mPropertyMap)); mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID); - std::list<NotifyArgs> args = - mDevice->configure(systemTime(), mReaderConfiguration, /*changes=*/{}); - ASSERT_THAT(args, testing::ElementsAre(testing::VariantWith<NotifyDeviceResetArgs>(_))); } void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max, diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h index 88057dc497..9353f8c9ff 100644 --- a/services/inputflinger/tests/InputMapperTest.h +++ b/services/inputflinger/tests/InputMapperTest.h @@ -43,13 +43,6 @@ protected: virtual void SetUp() override { SetUpWithBus(0); } virtual void SetUpWithBus(int bus); - /** - * Initializes mDevice and mDeviceContext. When this happens, mDevice takes a copy of - * mPropertyMap, so tests that need to set configuration properties should do so before calling - * this. Others will most likely want to call it in their SetUp method. - */ - void createDevice(); - void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution); void expectScanCodes(bool present, std::set<int> scanCodes); @@ -67,7 +60,7 @@ protected: MockEventHubInterface mMockEventHub; sp<FakeInputReaderPolicy> mFakePolicy; MockInputReaderContext mMockInputReaderContext; - std::unique_ptr<InputDevice> mDevice; + std::unique_ptr<MockInputDevice> mDevice; std::unique_ptr<InputDeviceContext> mDeviceContext; InputReaderConfiguration mReaderConfiguration; diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index 48e0b4f516..d51c708adb 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -26,6 +26,7 @@ #include <vector> #include <EventHub.h> +#include <InputDevice.h> #include <InputReaderBase.h> #include <InputReaderContext.h> #include <NotifyArgs.h> @@ -59,7 +60,7 @@ public: MOCK_METHOD(void, requestTimeoutAtTime, (nsecs_t when), (override)); int32_t bumpGeneration() override { return ++mGeneration; } - MOCK_METHOD(void, getExternalStylusDevices, (std::vector<InputDeviceInfo> & outDevices), + MOCK_METHOD(void, getExternalStylusDevices, (std::vector<InputDeviceInfo>& outDevices), (override)); MOCK_METHOD(std::list<NotifyArgs>, dispatchExternalStylusState, (const StylusState& outState), (override)); @@ -172,7 +173,7 @@ public: MOCK_METHOD(void, requestReopenDevices, (), (override)); MOCK_METHOD(void, wake, (), (override)); - MOCK_METHOD(void, dump, (std::string & dump), (const, override)); + MOCK_METHOD(void, dump, (std::string& dump), (const, override)); MOCK_METHOD(void, monitor, (), (const, override)); MOCK_METHOD(bool, isDeviceEnabled, (int32_t deviceId), (const, override)); MOCK_METHOD(status_t, enableDevice, (int32_t deviceId), (override)); @@ -190,4 +191,75 @@ public: MOCK_METHOD(void, notifyMouseCursorFadedOnTyping, (), (override)); }; +class MockInputDevice : public InputDevice { +public: + MockInputDevice(InputReaderContext* context, int32_t id, int32_t generation, + const InputDeviceIdentifier& identifier) + : InputDevice(context, id, generation, identifier) {} + + MOCK_METHOD(uint32_t, getSources, (), (const, override)); + MOCK_METHOD(bool, isEnabled, (), ()); + + MOCK_METHOD(void, dump, (std::string& dump, const std::string& eventHubDevStr), ()); + MOCK_METHOD(void, addEmptyEventHubDevice, (int32_t eventHubId), ()); + MOCK_METHOD(std::list<NotifyArgs>, addEventHubDevice, + (nsecs_t when, int32_t eventHubId, const InputReaderConfiguration& readerConfig), + ()); + MOCK_METHOD(void, removeEventHubDevice, (int32_t eventHubId), ()); + MOCK_METHOD(std::list<NotifyArgs>, configure, + (nsecs_t when, const InputReaderConfiguration& readerConfig, + ConfigurationChanges changes), + ()); + MOCK_METHOD(std::list<NotifyArgs>, reset, (nsecs_t when), ()); + MOCK_METHOD(std::list<NotifyArgs>, process, (const RawEvent* rawEvents, size_t count), ()); + MOCK_METHOD(std::list<NotifyArgs>, timeoutExpired, (nsecs_t when), ()); + MOCK_METHOD(std::list<NotifyArgs>, updateExternalStylusState, (const StylusState& state), ()); + + MOCK_METHOD(InputDeviceInfo, getDeviceInfo, (), ()); + MOCK_METHOD(int32_t, getKeyCodeState, (uint32_t sourceMask, int32_t keyCode), ()); + MOCK_METHOD(int32_t, getScanCodeState, (uint32_t sourceMask, int32_t scanCode), ()); + MOCK_METHOD(int32_t, getSwitchState, (uint32_t sourceMask, int32_t switchCode), ()); + MOCK_METHOD(int32_t, getKeyCodeForKeyLocation, (int32_t locationKeyCode), (const)); + MOCK_METHOD(bool, markSupportedKeyCodes, + (uint32_t sourceMask, const std::vector<int32_t>& keyCodes, uint8_t* outFlags), ()); + MOCK_METHOD(std::list<NotifyArgs>, vibrate, + (const VibrationSequence& sequence, ssize_t repeat, int32_t token), ()); + MOCK_METHOD(std::list<NotifyArgs>, cancelVibrate, (int32_t token), ()); + MOCK_METHOD(bool, isVibrating, (), ()); + MOCK_METHOD(std::vector<int32_t>, getVibratorIds, (), ()); + MOCK_METHOD(std::list<NotifyArgs>, cancelTouch, (nsecs_t when, nsecs_t readTime), ()); + MOCK_METHOD(bool, enableSensor, + (InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency), + ()); + + MOCK_METHOD(void, disableSensor, (InputDeviceSensorType sensorType), ()); + MOCK_METHOD(void, flushSensor, (InputDeviceSensorType sensorType), ()); + + MOCK_METHOD(std::optional<int32_t>, getBatteryEventHubId, (), (const)); + + MOCK_METHOD(bool, setLightColor, (int32_t lightId, int32_t color), ()); + MOCK_METHOD(bool, setLightPlayerId, (int32_t lightId, int32_t playerId), ()); + MOCK_METHOD(std::optional<int32_t>, getLightColor, (int32_t lightId), ()); + MOCK_METHOD(std::optional<int32_t>, getLightPlayerId, (int32_t lightId), ()); + + MOCK_METHOD(int32_t, getMetaState, (), ()); + MOCK_METHOD(void, updateMetaState, (int32_t keyCode), ()); + + MOCK_METHOD(void, addKeyRemapping, (int32_t fromKeyCode, int32_t toKeyCode), ()); + + MOCK_METHOD(void, setKeyboardType, (KeyboardType keyboardType), ()); + + MOCK_METHOD(void, bumpGeneration, (), ()); + + MOCK_METHOD(const PropertyMap&, getConfiguration, (), (const, override)); + + MOCK_METHOD(NotifyDeviceResetArgs, notifyReset, (nsecs_t when), ()); + + MOCK_METHOD(std::optional<ui::LogicalDisplayId>, getAssociatedDisplayId, (), ()); + + MOCK_METHOD(void, updateLedState, (bool reset), ()); + + MOCK_METHOD(size_t, getMapperCount, (), ()); +}; } // namespace android diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp index d3e8dee4a0..aa71e07a88 100644 --- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp +++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp @@ -55,7 +55,6 @@ protected: void SetUp() override { InputMapperUnitTest::SetUp(); - createDevice(); // set key-codes expected in tests for (const auto& [scanCode, outKeycode] : mKeyCodeMap) { diff --git a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp index d4d3c3857f..9a6b266b21 100644 --- a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp +++ b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp @@ -109,7 +109,6 @@ protected: mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0, /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL); - createDevice(); mMapper = createInputMapper<MultiTouchInputMapper>(*mDeviceContext, mFakePolicy->getReaderConfiguration()); } diff --git a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp index b441a23803..9ddb8c138d 100644 --- a/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp +++ b/services/inputflinger/tests/MultiTouchMotionAccumulator_test.cpp @@ -23,10 +23,7 @@ class MultiTouchMotionAccumulatorTest : public InputMapperUnitTest { protected: static constexpr size_t SLOT_COUNT = 8; - void SetUp() override { - InputMapperUnitTest::SetUp(); - createDevice(); - } + void SetUp() override { InputMapperUnitTest::SetUp(); } MultiTouchMotionAccumulator mMotionAccumulator; diff --git a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp index 366b3dcdd0..a796c49dbe 100644 --- a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp +++ b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp @@ -138,7 +138,6 @@ TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdWithAssociatedViewport) { mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport}); // Set up the secondary display as the associated viewport of the mapper. - createDevice(); ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); mMapper = createInputMapper<RotaryEncoderInputMapper>(deviceContext, mReaderConfiguration); @@ -159,7 +158,6 @@ TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdNoAssociatedViewport) { mFakePolicy->addDisplayViewport(createPrimaryViewport()); // Set up the mapper with no associated viewport. - createDevice(); mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration); // Ensure input events are generated without display ID @@ -174,7 +172,6 @@ TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdNoAssociatedViewport) { } TEST_F(RotaryEncoderInputMapperTest, ProcessRegularScroll) { - createDevice(); mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration); std::list<NotifyArgs> args; @@ -191,7 +188,6 @@ TEST_F(RotaryEncoderInputMapperTest, ProcessHighResScroll) { vd_flags::high_resolution_scroll(true); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) .WillRepeatedly(Return(true)); - createDevice(); mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration); std::list<NotifyArgs> args; @@ -208,7 +204,6 @@ TEST_F(RotaryEncoderInputMapperTest, HighResScrollIgnoresRegularScroll) { vd_flags::high_resolution_scroll(true); EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES)) .WillRepeatedly(Return(true)); - createDevice(); mMapper = createInputMapper<RotaryEncoderInputMapper>(*mDeviceContext, mReaderConfiguration); std::list<NotifyArgs> args; diff --git a/services/inputflinger/tests/SwitchInputMapper_test.cpp b/services/inputflinger/tests/SwitchInputMapper_test.cpp index 4020e78701..ebbf10b8db 100644 --- a/services/inputflinger/tests/SwitchInputMapper_test.cpp +++ b/services/inputflinger/tests/SwitchInputMapper_test.cpp @@ -33,7 +33,6 @@ class SwitchInputMapperTest : public InputMapperUnitTest { protected: void SetUp() override { InputMapperUnitTest::SetUp(); - createDevice(); mMapper = createInputMapper<SwitchInputMapper>(*mDeviceContext, mFakePolicy->getReaderConfiguration()); } diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp index 1afb4f090a..fc8a7dafb0 100644 --- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp +++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp @@ -109,7 +109,6 @@ protected: .WillRepeatedly([]() -> base::Result<std::vector<int32_t>> { return base::ResultError("Axis not supported", NAME_NOT_FOUND); }); - createDevice(); mMapper = createInputMapper<TouchpadInputMapper>(*mDeviceContext, mReaderConfiguration); } }; diff --git a/services/inputflinger/tests/VibratorInputMapper_test.cpp b/services/inputflinger/tests/VibratorInputMapper_test.cpp index aa4a6bb382..6e3344c345 100644 --- a/services/inputflinger/tests/VibratorInputMapper_test.cpp +++ b/services/inputflinger/tests/VibratorInputMapper_test.cpp @@ -36,7 +36,6 @@ class VibratorInputMapperTest : public InputMapperUnitTest { protected: void SetUp() override { InputMapperUnitTest::SetUp(); - createDevice(); EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID)) .WillRepeatedly(testing::Return(InputDeviceClass::VIBRATOR)); EXPECT_CALL(mMockEventHub, getVibratorIds(EVENTHUB_ID)) |