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

Commit 20007465 authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Cherrypicker Worker
Browse files

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
Bug: 353128452
Test: atest inputflinger_tests
Flag: EXEMPT refactor
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:31d05c4c78e7924e4bb6dc45092e612a9c7d5bfb)
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:76a4212fb43aa1f6f34e5a03addc5a932defe649)
Merged-In: Id7e103e1f04812c92ee8ecfdfe1e75a9949efa9e
Change-Id: Id7e103e1f04812c92ee8ecfdfe1e75a9949efa9e
parent 44981070
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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();
+0 −7
Original line number Diff line number Diff line
@@ -157,7 +157,6 @@ protected:
    }

    void createMapper() {
        createDevice();
        mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
    }

@@ -535,7 +534,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);

@@ -553,7 +551,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);

@@ -645,7 +642,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);

@@ -666,7 +662,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);
@@ -959,7 +954,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);

@@ -997,7 +991,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,
+5 −8
Original line number Diff line number Diff line
@@ -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,
    mDevice = std::make_unique<NiceMock<MockInputDevice>>(&mMockInputReaderContext, DEVICE_ID,
                                                          /*generation=*/2, mIdentifier);
    mDevice->addEmptyEventHubDevice(EVENTHUB_ID);
    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,
+1 −8
Original line number Diff line number Diff line
@@ -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);
@@ -65,7 +58,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;
+74 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <vector>

#include <EventHub.h>
#include <InputDevice.h>
#include <InputReaderBase.h>
#include <InputReaderContext.h>
#include <NotifyArgs.h>
@@ -189,4 +190,75 @@ public:
    MOCK_METHOD(bool, isInputMethodConnectionActive, (), (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
Loading