Loading services/inputflinger/tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ cc_test { "-Werror", "-Wextra", "-Wno-unused-parameter", "-Wthread-safety", ], shared_libs: [ "android.hardware.input.classifier@1.0", Loading services/inputflinger/tests/InputReader_test.cpp +100 −33 Original line number Diff line number Diff line Loading @@ -25,13 +25,18 @@ #include <TestInputListener.h> #include <TouchInputMapper.h> #include <android-base/thread_annotations.h> #include <gtest/gtest.h> #include <inttypes.h> #include <math.h> namespace android { using std::chrono_literals::operator""ms; // Timeout for waiting for an expected event static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms; // An arbitrary time value. static const nsecs_t ARBITRARY_TIME = 1234; Loading Loading @@ -164,9 +169,13 @@ private: // --- FakeInputReaderPolicy --- class FakeInputReaderPolicy : public InputReaderPolicyInterface { std::mutex mLock; std::condition_variable mDevicesChangedCondition; InputReaderConfiguration mConfig; KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers; std::vector<InputDeviceInfo> mInputDevices; std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock); bool mInputDevicesChanged GUARDED_BY(mLock){false}; std::vector<DisplayViewport> mViewports; TouchAffineTransformation transform; Loading @@ -177,6 +186,20 @@ public: FakeInputReaderPolicy() { } void assertInputDevicesChanged() { std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool devicesChanged = mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mInputDevicesChanged; }); if (!devicesChanged) { FAIL() << "Timed out waiting for notifyInputDevicesChanged() to be called."; } mInputDevicesChanged = false; } virtual void clearViewports() { mViewports.clear(); mConfig.setDisplayViewports(mViewports); Loading Loading @@ -291,7 +314,10 @@ private: } virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) { std::scoped_lock<std::mutex> lock(mLock); mInputDevices = inputDevices; mInputDevicesChanged = true; mDevicesChangedCondition.notify_all(); } virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier&) { Loading Loading @@ -342,9 +368,12 @@ class FakeEventHub : public EventHubInterface { } }; std::mutex mLock; std::condition_variable mEventsCondition; KeyedVector<int32_t, Device*> mDevices; std::vector<std::string> mExcludedDevices; List<RawEvent> mEvents; List<RawEvent> mEvents GUARDED_BY(mLock); std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames; public: Loading Loading @@ -496,6 +525,7 @@ public: void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type, int32_t code, int32_t value) { std::scoped_lock<std::mutex> lock(mLock); RawEvent event; event.when = when; event.deviceId = deviceId; Loading @@ -515,8 +545,14 @@ public: } void assertQueueIsEmpty() { ASSERT_EQ(size_t(0), mEvents.size()) << "Expected the event queue to be empty (fully consumed)."; std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool queueIsEmpty = mEventsCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mEvents.size() == 0; }); if (!queueIsEmpty) { FAIL() << "Timed out waiting for EventHub queue to be emptied."; } } private: Loading Loading @@ -619,12 +655,14 @@ private: } virtual size_t getEvents(int, RawEvent* buffer, size_t) { std::scoped_lock<std::mutex> lock(mLock); if (mEvents.empty()) { return 0; } *buffer = *mEvents.begin(); mEvents.erase(mEvents.begin()); mEventsCondition.notify_all(); return 1; } Loading Loading @@ -877,11 +915,13 @@ class FakeInputMapper : public InputMapper { KeyedVector<int32_t, int32_t> mScanCodeStates; KeyedVector<int32_t, int32_t> mSwitchStates; std::vector<int32_t> mSupportedKeyCodes; RawEvent mLastEvent; bool mConfigureWasCalled; bool mResetWasCalled; bool mProcessWasCalled; std::mutex mLock; std::condition_variable mStateChangedCondition; bool mConfigureWasCalled GUARDED_BY(mLock); bool mResetWasCalled GUARDED_BY(mLock); bool mProcessWasCalled GUARDED_BY(mLock); RawEvent mLastEvent GUARDED_BY(mLock); std::optional<DisplayViewport> mViewport; public: Loading @@ -903,20 +943,41 @@ public: } void assertConfigureWasCalled() { ASSERT_TRUE(mConfigureWasCalled) << "Expected configure() to have been called."; std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool configureCalled = mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mConfigureWasCalled; }); if (!configureCalled) { FAIL() << "Expected configure() to have been called."; } mConfigureWasCalled = false; } void assertResetWasCalled() { ASSERT_TRUE(mResetWasCalled) << "Expected reset() to have been called."; std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool resetCalled = mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mResetWasCalled; }); if (!resetCalled) { FAIL() << "Expected reset() to have been called."; } mResetWasCalled = false; } void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) { ASSERT_TRUE(mProcessWasCalled) << "Expected process() to have been called."; std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool processCalled = mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mProcessWasCalled; }); if (!processCalled) { FAIL() << "Expected process() to have been called."; } if (outLastEvent) { *outLastEvent = mLastEvent; } Loading Loading @@ -953,6 +1014,7 @@ private: } virtual void configure(nsecs_t, const InputReaderConfiguration* config, uint32_t changes) { std::scoped_lock<std::mutex> lock(mLock); mConfigureWasCalled = true; // Find the associated viewport if exist. Loading @@ -960,15 +1022,21 @@ private: if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { mViewport = config->getDisplayViewportByPort(*displayPort); } mStateChangedCondition.notify_all(); } virtual void reset(nsecs_t) { std::scoped_lock<std::mutex> lock(mLock); mResetWasCalled = true; mStateChangedCondition.notify_all(); } virtual void process(const RawEvent* rawEvent) { std::scoped_lock<std::mutex> lock(mLock); mLastEvent = *rawEvent; mProcessWasCalled = true; mStateChangedCondition.notify_all(); } virtual int32_t getKeyCodeState(uint32_t, int32_t keyCode) { Loading Loading @@ -1033,9 +1101,7 @@ public: } } void setNextDevice(InputDevice* device) { mNextDevice = device; } void setNextDevice(InputDevice* device) { mNextDevice = device; } InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const std::string& name, uint32_t classes, const std::string& location = "") { Loading @@ -1049,7 +1115,8 @@ public: protected: virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) { const InputDeviceIdentifier& identifier, uint32_t classes) { if (mNextDevice) { InputDevice* device = mNextDevice; mNextDevice = nullptr; Loading Loading @@ -1281,7 +1348,8 @@ protected: mFakeEventHub->finishDeviceScan(); mReader->loopOnce(); mReader->loopOnce(); mFakeEventHub->assertQueueIsEmpty(); ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged()); ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty()); } void disableDevice(int32_t deviceId, InputDevice* device) { Loading Loading @@ -1316,10 +1384,8 @@ TEST_F(InputReaderTest, GetInputDevices) { ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", 0, nullptr)); // no classes so device will be ignored std::vector<InputDeviceInfo> inputDevices; mReader->getInputDevices(inputDevices); ASSERT_EQ(1U, inputDevices.size()); ASSERT_EQ(1, inputDevices[0].getId()); ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str()); Loading @@ -1345,7 +1411,7 @@ TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); mReader->setNextDevice(device); addDevice(deviceId, "fake", deviceClass, nullptr); ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr)); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr)); Loading @@ -1358,20 +1424,20 @@ TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { disableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime); ASSERT_EQ(deviceId, resetArgs.deviceId); ASSERT_EQ(device->isEnabled(), false); disableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasNotCalled(); mFakeListener->assertNotifyConfigurationChangedWasNotCalled(); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled()); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasNotCalled()); ASSERT_EQ(device->isEnabled(), false); enableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime); ASSERT_EQ(deviceId, resetArgs.deviceId); ASSERT_EQ(device->isEnabled(), true); Loading Loading @@ -1529,7 +1595,7 @@ TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) { FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); mReader->setNextDevice(device); addDevice(deviceId, "fake", deviceClass, nullptr); ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr)); NotifyDeviceResetArgs resetArgs; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); Loading @@ -1537,19 +1603,19 @@ TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) { disableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum); prevSequenceNum = resetArgs.sequenceNum; enableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum); prevSequenceNum = resetArgs.sequenceNum; disableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum); prevSequenceNum = resetArgs.sequenceNum; } Loading Loading @@ -1577,6 +1643,7 @@ TEST_F(InputReaderTest, Device_CanDispatchToDisplay) { DISPLAY_ORIENTATION_0, "local:1", hdmi1, ViewportType::VIEWPORT_EXTERNAL); mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO); mReader->loopOnce(); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled()); // Device should only dispatch to the specified display. ASSERT_EQ(deviceId, device->getId()); Loading services/inputflinger/tests/TestInputListener.cpp +79 −40 Original line number Diff line number Diff line Loading @@ -19,6 +19,15 @@ #include "TestInputListener.h" namespace { using std::chrono_literals::operator""ms; // Timeout for waiting for an expected event static constexpr std::chrono::duration WAIT_TIMEOUT = 5ms; } // namespace namespace android { // --- TestInputListener --- Loading @@ -29,87 +38,117 @@ TestInputListener::~TestInputListener() { } void TestInputListener::assertNotifyConfigurationChangedWasCalled( NotifyConfigurationChangedArgs* outEventArgs) { ASSERT_FALSE(mNotifyConfigurationChangedArgsQueue.empty()) << "Expected notifyConfigurationChanged() to have been called."; if (outEventArgs) { *outEventArgs = *mNotifyConfigurationChangedArgsQueue.begin(); } mNotifyConfigurationChangedArgsQueue.erase(mNotifyConfigurationChangedArgsQueue.begin()); ASSERT_NO_FATAL_FAILURE( assertCalled<NotifyConfigurationChangedArgs>(outEventArgs, "Expected notifyConfigurationChanged() " "to have been called.")); } void TestInputListener::assertNotifyConfigurationChangedWasNotCalled() { ASSERT_TRUE(mNotifyConfigurationChangedArgsQueue.empty()) << "Expected notifyConfigurationChanged() to not have been called."; ASSERT_NO_FATAL_FAILURE(assertNotCalled<NotifyConfigurationChangedArgs>( "notifyConfigurationChanged() should not be called.")); } void TestInputListener::assertNotifyDeviceResetWasCalled( NotifyDeviceResetArgs* outEventArgs) { ASSERT_FALSE(mNotifyDeviceResetArgsQueue.empty()) << "Expected notifyDeviceReset() to have been called."; if (outEventArgs) { *outEventArgs = *mNotifyDeviceResetArgsQueue.begin(); } mNotifyDeviceResetArgsQueue.erase(mNotifyDeviceResetArgsQueue.begin()); ASSERT_NO_FATAL_FAILURE( assertCalled< NotifyDeviceResetArgs>(outEventArgs, "Expected notifyDeviceReset() to have been called.")); } void TestInputListener::assertNotifyDeviceResetWasNotCalled() { ASSERT_TRUE(mNotifyDeviceResetArgsQueue.empty()) << "Expected notifyDeviceReset() to not have been called."; ASSERT_NO_FATAL_FAILURE( assertNotCalled<NotifyDeviceResetArgs>("notifyDeviceReset() should not be called.")); } void TestInputListener::assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs) { ASSERT_FALSE(mNotifyKeyArgsQueue.empty()) << "Expected notifyKey() to have been called."; if (outEventArgs) { *outEventArgs = *mNotifyKeyArgsQueue.begin(); } mNotifyKeyArgsQueue.erase(mNotifyKeyArgsQueue.begin()); ASSERT_NO_FATAL_FAILURE( assertCalled<NotifyKeyArgs>(outEventArgs, "Expected notifyKey() to have been called.")); } void TestInputListener::assertNotifyKeyWasNotCalled() { ASSERT_TRUE(mNotifyKeyArgsQueue.empty()) << "Expected notifyKey() to not have been called."; ASSERT_NO_FATAL_FAILURE(assertNotCalled<NotifyKeyArgs>("notifyKey() should not be called.")); } void TestInputListener::assertNotifyMotionWasCalled(NotifyMotionArgs* outEventArgs) { ASSERT_FALSE(mNotifyMotionArgsQueue.empty()) << "Expected notifyMotion() to have been called."; if (outEventArgs) { *outEventArgs = *mNotifyMotionArgsQueue.begin(); } mNotifyMotionArgsQueue.erase(mNotifyMotionArgsQueue.begin()); ASSERT_NO_FATAL_FAILURE( assertCalled<NotifyMotionArgs>(outEventArgs, "Expected notifyMotion() to have been called.")); } void TestInputListener::assertNotifyMotionWasNotCalled() { ASSERT_TRUE(mNotifyMotionArgsQueue.empty()) << "Expected notifyMotion() to not have been called."; ASSERT_NO_FATAL_FAILURE( assertNotCalled<NotifySwitchArgs>("notifySwitch() should not be called.")); } void TestInputListener::assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs) { ASSERT_FALSE(mNotifySwitchArgsQueue.empty()) << "Expected notifySwitch() to have been called."; ASSERT_NO_FATAL_FAILURE( assertCalled<NotifySwitchArgs>(outEventArgs, "Expected notifySwitch() to have been called.")); } template <class NotifyArgsType> void TestInputListener::assertCalled(NotifyArgsType* outEventArgs, std::string message) { std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues); if (queue.empty()) { const bool eventReceived = mCondition.wait_for(lock, WAIT_TIMEOUT, [&queue]() REQUIRES(mLock) { return !queue.empty(); }); if (!eventReceived) { FAIL() << "Timed out waiting for event: " << message.c_str(); } } if (outEventArgs) { *outEventArgs = *mNotifySwitchArgsQueue.begin(); *outEventArgs = *queue.begin(); } queue.erase(queue.begin()); } template <class NotifyArgsType> void TestInputListener::assertNotCalled(std::string message) { std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues); const bool eventReceived = mCondition.wait_for(lock, WAIT_TIMEOUT, [&queue]() REQUIRES(mLock) { return !queue.empty(); }); if (eventReceived) { FAIL() << "Unexpected event: " << message.c_str(); } } mNotifySwitchArgsQueue.erase(mNotifySwitchArgsQueue.begin()); template <class NotifyArgsType> void TestInputListener::notify(const NotifyArgsType* args) { std::scoped_lock<std::mutex> lock(mLock); std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues); queue.push_back(*args); mCondition.notify_all(); } void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { mNotifyConfigurationChangedArgsQueue.push_back(*args); notify<NotifyConfigurationChangedArgs>(args); } void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) { mNotifyDeviceResetArgsQueue.push_back(*args); notify<NotifyDeviceResetArgs>(args); } void TestInputListener::notifyKey(const NotifyKeyArgs* args) { mNotifyKeyArgsQueue.push_back(*args); notify<NotifyKeyArgs>(args); } void TestInputListener::notifyMotion(const NotifyMotionArgs* args) { mNotifyMotionArgsQueue.push_back(*args); notify<NotifyMotionArgs>(args); } void TestInputListener::notifySwitch(const NotifySwitchArgs* args) { mNotifySwitchArgsQueue.push_back(*args); notify<NotifySwitchArgs>(args); } } // namespace android services/inputflinger/tests/TestInputListener.h +25 −12 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef _UI_TEST_INPUT_LISTENER_H #define _UI_TEST_INPUT_LISTENER_H #include <android-base/thread_annotations.h> #include <gtest/gtest.h> #include "InputListener.h" Loading @@ -25,13 +26,6 @@ namespace android { // --- TestInputListener --- class TestInputListener : public InputListenerInterface { private: std::vector<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgsQueue; std::vector<NotifyDeviceResetArgs> mNotifyDeviceResetArgsQueue; std::vector<NotifyKeyArgs> mNotifyKeyArgsQueue; std::vector<NotifyMotionArgs> mNotifyMotionArgsQueue; std::vector<NotifySwitchArgs> mNotifySwitchArgsQueue; protected: virtual ~TestInputListener(); Loading @@ -58,15 +52,34 @@ public: void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = nullptr); private: virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args); template <class NotifyArgsType> void assertCalled(NotifyArgsType* outEventArgs, std::string message); template <class NotifyArgsType> void assertNotCalled(std::string message); template <class NotifyArgsType> void notify(const NotifyArgsType* args); virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args); virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifyKey(const NotifyKeyArgs* args); virtual void notifySwitch(const NotifySwitchArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args); std::mutex mLock; std::condition_variable mCondition; virtual void notifySwitch(const NotifySwitchArgs* args); std::tuple<std::vector<NotifyConfigurationChangedArgs>, // std::vector<NotifyDeviceResetArgs>, // std::vector<NotifyKeyArgs>, // std::vector<NotifyMotionArgs>, // std::vector<NotifySwitchArgs>> // mQueues GUARDED_BY(mLock); }; } // namespace android Loading Loading
services/inputflinger/tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ cc_test { "-Werror", "-Wextra", "-Wno-unused-parameter", "-Wthread-safety", ], shared_libs: [ "android.hardware.input.classifier@1.0", Loading
services/inputflinger/tests/InputReader_test.cpp +100 −33 Original line number Diff line number Diff line Loading @@ -25,13 +25,18 @@ #include <TestInputListener.h> #include <TouchInputMapper.h> #include <android-base/thread_annotations.h> #include <gtest/gtest.h> #include <inttypes.h> #include <math.h> namespace android { using std::chrono_literals::operator""ms; // Timeout for waiting for an expected event static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms; // An arbitrary time value. static const nsecs_t ARBITRARY_TIME = 1234; Loading Loading @@ -164,9 +169,13 @@ private: // --- FakeInputReaderPolicy --- class FakeInputReaderPolicy : public InputReaderPolicyInterface { std::mutex mLock; std::condition_variable mDevicesChangedCondition; InputReaderConfiguration mConfig; KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers; std::vector<InputDeviceInfo> mInputDevices; std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock); bool mInputDevicesChanged GUARDED_BY(mLock){false}; std::vector<DisplayViewport> mViewports; TouchAffineTransformation transform; Loading @@ -177,6 +186,20 @@ public: FakeInputReaderPolicy() { } void assertInputDevicesChanged() { std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool devicesChanged = mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mInputDevicesChanged; }); if (!devicesChanged) { FAIL() << "Timed out waiting for notifyInputDevicesChanged() to be called."; } mInputDevicesChanged = false; } virtual void clearViewports() { mViewports.clear(); mConfig.setDisplayViewports(mViewports); Loading Loading @@ -291,7 +314,10 @@ private: } virtual void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) { std::scoped_lock<std::mutex> lock(mLock); mInputDevices = inputDevices; mInputDevicesChanged = true; mDevicesChangedCondition.notify_all(); } virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier&) { Loading Loading @@ -342,9 +368,12 @@ class FakeEventHub : public EventHubInterface { } }; std::mutex mLock; std::condition_variable mEventsCondition; KeyedVector<int32_t, Device*> mDevices; std::vector<std::string> mExcludedDevices; List<RawEvent> mEvents; List<RawEvent> mEvents GUARDED_BY(mLock); std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames; public: Loading Loading @@ -496,6 +525,7 @@ public: void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type, int32_t code, int32_t value) { std::scoped_lock<std::mutex> lock(mLock); RawEvent event; event.when = when; event.deviceId = deviceId; Loading @@ -515,8 +545,14 @@ public: } void assertQueueIsEmpty() { ASSERT_EQ(size_t(0), mEvents.size()) << "Expected the event queue to be empty (fully consumed)."; std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool queueIsEmpty = mEventsCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mEvents.size() == 0; }); if (!queueIsEmpty) { FAIL() << "Timed out waiting for EventHub queue to be emptied."; } } private: Loading Loading @@ -619,12 +655,14 @@ private: } virtual size_t getEvents(int, RawEvent* buffer, size_t) { std::scoped_lock<std::mutex> lock(mLock); if (mEvents.empty()) { return 0; } *buffer = *mEvents.begin(); mEvents.erase(mEvents.begin()); mEventsCondition.notify_all(); return 1; } Loading Loading @@ -877,11 +915,13 @@ class FakeInputMapper : public InputMapper { KeyedVector<int32_t, int32_t> mScanCodeStates; KeyedVector<int32_t, int32_t> mSwitchStates; std::vector<int32_t> mSupportedKeyCodes; RawEvent mLastEvent; bool mConfigureWasCalled; bool mResetWasCalled; bool mProcessWasCalled; std::mutex mLock; std::condition_variable mStateChangedCondition; bool mConfigureWasCalled GUARDED_BY(mLock); bool mResetWasCalled GUARDED_BY(mLock); bool mProcessWasCalled GUARDED_BY(mLock); RawEvent mLastEvent GUARDED_BY(mLock); std::optional<DisplayViewport> mViewport; public: Loading @@ -903,20 +943,41 @@ public: } void assertConfigureWasCalled() { ASSERT_TRUE(mConfigureWasCalled) << "Expected configure() to have been called."; std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool configureCalled = mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mConfigureWasCalled; }); if (!configureCalled) { FAIL() << "Expected configure() to have been called."; } mConfigureWasCalled = false; } void assertResetWasCalled() { ASSERT_TRUE(mResetWasCalled) << "Expected reset() to have been called."; std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool resetCalled = mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mResetWasCalled; }); if (!resetCalled) { FAIL() << "Expected reset() to have been called."; } mResetWasCalled = false; } void assertProcessWasCalled(RawEvent* outLastEvent = nullptr) { ASSERT_TRUE(mProcessWasCalled) << "Expected process() to have been called."; std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); const bool processCalled = mStateChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { return mProcessWasCalled; }); if (!processCalled) { FAIL() << "Expected process() to have been called."; } if (outLastEvent) { *outLastEvent = mLastEvent; } Loading Loading @@ -953,6 +1014,7 @@ private: } virtual void configure(nsecs_t, const InputReaderConfiguration* config, uint32_t changes) { std::scoped_lock<std::mutex> lock(mLock); mConfigureWasCalled = true; // Find the associated viewport if exist. Loading @@ -960,15 +1022,21 @@ private: if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { mViewport = config->getDisplayViewportByPort(*displayPort); } mStateChangedCondition.notify_all(); } virtual void reset(nsecs_t) { std::scoped_lock<std::mutex> lock(mLock); mResetWasCalled = true; mStateChangedCondition.notify_all(); } virtual void process(const RawEvent* rawEvent) { std::scoped_lock<std::mutex> lock(mLock); mLastEvent = *rawEvent; mProcessWasCalled = true; mStateChangedCondition.notify_all(); } virtual int32_t getKeyCodeState(uint32_t, int32_t keyCode) { Loading Loading @@ -1033,9 +1101,7 @@ public: } } void setNextDevice(InputDevice* device) { mNextDevice = device; } void setNextDevice(InputDevice* device) { mNextDevice = device; } InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const std::string& name, uint32_t classes, const std::string& location = "") { Loading @@ -1049,7 +1115,8 @@ public: protected: virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) { const InputDeviceIdentifier& identifier, uint32_t classes) { if (mNextDevice) { InputDevice* device = mNextDevice; mNextDevice = nullptr; Loading Loading @@ -1281,7 +1348,8 @@ protected: mFakeEventHub->finishDeviceScan(); mReader->loopOnce(); mReader->loopOnce(); mFakeEventHub->assertQueueIsEmpty(); ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged()); ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty()); } void disableDevice(int32_t deviceId, InputDevice* device) { Loading Loading @@ -1316,10 +1384,8 @@ TEST_F(InputReaderTest, GetInputDevices) { ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", 0, nullptr)); // no classes so device will be ignored std::vector<InputDeviceInfo> inputDevices; mReader->getInputDevices(inputDevices); ASSERT_EQ(1U, inputDevices.size()); ASSERT_EQ(1, inputDevices[0].getId()); ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str()); Loading @@ -1345,7 +1411,7 @@ TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); mReader->setNextDevice(device); addDevice(deviceId, "fake", deviceClass, nullptr); ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr)); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr)); Loading @@ -1358,20 +1424,20 @@ TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { disableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime); ASSERT_EQ(deviceId, resetArgs.deviceId); ASSERT_EQ(device->isEnabled(), false); disableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasNotCalled(); mFakeListener->assertNotifyConfigurationChangedWasNotCalled(); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled()); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasNotCalled()); ASSERT_EQ(device->isEnabled(), false); enableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime); ASSERT_EQ(deviceId, resetArgs.deviceId); ASSERT_EQ(device->isEnabled(), true); Loading Loading @@ -1529,7 +1595,7 @@ TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) { FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); mReader->setNextDevice(device); addDevice(deviceId, "fake", deviceClass, nullptr); ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr)); NotifyDeviceResetArgs resetArgs; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); Loading @@ -1537,19 +1603,19 @@ TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) { disableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum); prevSequenceNum = resetArgs.sequenceNum; enableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum); prevSequenceNum = resetArgs.sequenceNum; disableDevice(deviceId, device); mReader->loopOnce(); mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum); prevSequenceNum = resetArgs.sequenceNum; } Loading Loading @@ -1577,6 +1643,7 @@ TEST_F(InputReaderTest, Device_CanDispatchToDisplay) { DISPLAY_ORIENTATION_0, "local:1", hdmi1, ViewportType::VIEWPORT_EXTERNAL); mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO); mReader->loopOnce(); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled()); // Device should only dispatch to the specified display. ASSERT_EQ(deviceId, device->getId()); Loading
services/inputflinger/tests/TestInputListener.cpp +79 −40 Original line number Diff line number Diff line Loading @@ -19,6 +19,15 @@ #include "TestInputListener.h" namespace { using std::chrono_literals::operator""ms; // Timeout for waiting for an expected event static constexpr std::chrono::duration WAIT_TIMEOUT = 5ms; } // namespace namespace android { // --- TestInputListener --- Loading @@ -29,87 +38,117 @@ TestInputListener::~TestInputListener() { } void TestInputListener::assertNotifyConfigurationChangedWasCalled( NotifyConfigurationChangedArgs* outEventArgs) { ASSERT_FALSE(mNotifyConfigurationChangedArgsQueue.empty()) << "Expected notifyConfigurationChanged() to have been called."; if (outEventArgs) { *outEventArgs = *mNotifyConfigurationChangedArgsQueue.begin(); } mNotifyConfigurationChangedArgsQueue.erase(mNotifyConfigurationChangedArgsQueue.begin()); ASSERT_NO_FATAL_FAILURE( assertCalled<NotifyConfigurationChangedArgs>(outEventArgs, "Expected notifyConfigurationChanged() " "to have been called.")); } void TestInputListener::assertNotifyConfigurationChangedWasNotCalled() { ASSERT_TRUE(mNotifyConfigurationChangedArgsQueue.empty()) << "Expected notifyConfigurationChanged() to not have been called."; ASSERT_NO_FATAL_FAILURE(assertNotCalled<NotifyConfigurationChangedArgs>( "notifyConfigurationChanged() should not be called.")); } void TestInputListener::assertNotifyDeviceResetWasCalled( NotifyDeviceResetArgs* outEventArgs) { ASSERT_FALSE(mNotifyDeviceResetArgsQueue.empty()) << "Expected notifyDeviceReset() to have been called."; if (outEventArgs) { *outEventArgs = *mNotifyDeviceResetArgsQueue.begin(); } mNotifyDeviceResetArgsQueue.erase(mNotifyDeviceResetArgsQueue.begin()); ASSERT_NO_FATAL_FAILURE( assertCalled< NotifyDeviceResetArgs>(outEventArgs, "Expected notifyDeviceReset() to have been called.")); } void TestInputListener::assertNotifyDeviceResetWasNotCalled() { ASSERT_TRUE(mNotifyDeviceResetArgsQueue.empty()) << "Expected notifyDeviceReset() to not have been called."; ASSERT_NO_FATAL_FAILURE( assertNotCalled<NotifyDeviceResetArgs>("notifyDeviceReset() should not be called.")); } void TestInputListener::assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs) { ASSERT_FALSE(mNotifyKeyArgsQueue.empty()) << "Expected notifyKey() to have been called."; if (outEventArgs) { *outEventArgs = *mNotifyKeyArgsQueue.begin(); } mNotifyKeyArgsQueue.erase(mNotifyKeyArgsQueue.begin()); ASSERT_NO_FATAL_FAILURE( assertCalled<NotifyKeyArgs>(outEventArgs, "Expected notifyKey() to have been called.")); } void TestInputListener::assertNotifyKeyWasNotCalled() { ASSERT_TRUE(mNotifyKeyArgsQueue.empty()) << "Expected notifyKey() to not have been called."; ASSERT_NO_FATAL_FAILURE(assertNotCalled<NotifyKeyArgs>("notifyKey() should not be called.")); } void TestInputListener::assertNotifyMotionWasCalled(NotifyMotionArgs* outEventArgs) { ASSERT_FALSE(mNotifyMotionArgsQueue.empty()) << "Expected notifyMotion() to have been called."; if (outEventArgs) { *outEventArgs = *mNotifyMotionArgsQueue.begin(); } mNotifyMotionArgsQueue.erase(mNotifyMotionArgsQueue.begin()); ASSERT_NO_FATAL_FAILURE( assertCalled<NotifyMotionArgs>(outEventArgs, "Expected notifyMotion() to have been called.")); } void TestInputListener::assertNotifyMotionWasNotCalled() { ASSERT_TRUE(mNotifyMotionArgsQueue.empty()) << "Expected notifyMotion() to not have been called."; ASSERT_NO_FATAL_FAILURE( assertNotCalled<NotifySwitchArgs>("notifySwitch() should not be called.")); } void TestInputListener::assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs) { ASSERT_FALSE(mNotifySwitchArgsQueue.empty()) << "Expected notifySwitch() to have been called."; ASSERT_NO_FATAL_FAILURE( assertCalled<NotifySwitchArgs>(outEventArgs, "Expected notifySwitch() to have been called.")); } template <class NotifyArgsType> void TestInputListener::assertCalled(NotifyArgsType* outEventArgs, std::string message) { std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues); if (queue.empty()) { const bool eventReceived = mCondition.wait_for(lock, WAIT_TIMEOUT, [&queue]() REQUIRES(mLock) { return !queue.empty(); }); if (!eventReceived) { FAIL() << "Timed out waiting for event: " << message.c_str(); } } if (outEventArgs) { *outEventArgs = *mNotifySwitchArgsQueue.begin(); *outEventArgs = *queue.begin(); } queue.erase(queue.begin()); } template <class NotifyArgsType> void TestInputListener::assertNotCalled(std::string message) { std::unique_lock<std::mutex> lock(mLock); base::ScopedLockAssertion assumeLocked(mLock); std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues); const bool eventReceived = mCondition.wait_for(lock, WAIT_TIMEOUT, [&queue]() REQUIRES(mLock) { return !queue.empty(); }); if (eventReceived) { FAIL() << "Unexpected event: " << message.c_str(); } } mNotifySwitchArgsQueue.erase(mNotifySwitchArgsQueue.begin()); template <class NotifyArgsType> void TestInputListener::notify(const NotifyArgsType* args) { std::scoped_lock<std::mutex> lock(mLock); std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues); queue.push_back(*args); mCondition.notify_all(); } void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) { mNotifyConfigurationChangedArgsQueue.push_back(*args); notify<NotifyConfigurationChangedArgs>(args); } void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) { mNotifyDeviceResetArgsQueue.push_back(*args); notify<NotifyDeviceResetArgs>(args); } void TestInputListener::notifyKey(const NotifyKeyArgs* args) { mNotifyKeyArgsQueue.push_back(*args); notify<NotifyKeyArgs>(args); } void TestInputListener::notifyMotion(const NotifyMotionArgs* args) { mNotifyMotionArgsQueue.push_back(*args); notify<NotifyMotionArgs>(args); } void TestInputListener::notifySwitch(const NotifySwitchArgs* args) { mNotifySwitchArgsQueue.push_back(*args); notify<NotifySwitchArgs>(args); } } // namespace android
services/inputflinger/tests/TestInputListener.h +25 −12 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef _UI_TEST_INPUT_LISTENER_H #define _UI_TEST_INPUT_LISTENER_H #include <android-base/thread_annotations.h> #include <gtest/gtest.h> #include "InputListener.h" Loading @@ -25,13 +26,6 @@ namespace android { // --- TestInputListener --- class TestInputListener : public InputListenerInterface { private: std::vector<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgsQueue; std::vector<NotifyDeviceResetArgs> mNotifyDeviceResetArgsQueue; std::vector<NotifyKeyArgs> mNotifyKeyArgsQueue; std::vector<NotifyMotionArgs> mNotifyMotionArgsQueue; std::vector<NotifySwitchArgs> mNotifySwitchArgsQueue; protected: virtual ~TestInputListener(); Loading @@ -58,15 +52,34 @@ public: void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = nullptr); private: virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args); template <class NotifyArgsType> void assertCalled(NotifyArgsType* outEventArgs, std::string message); template <class NotifyArgsType> void assertNotCalled(std::string message); template <class NotifyArgsType> void notify(const NotifyArgsType* args); virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args); virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifyKey(const NotifyKeyArgs* args); virtual void notifySwitch(const NotifySwitchArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args); std::mutex mLock; std::condition_variable mCondition; virtual void notifySwitch(const NotifySwitchArgs* args); std::tuple<std::vector<NotifyConfigurationChangedArgs>, // std::vector<NotifyDeviceResetArgs>, // std::vector<NotifyKeyArgs>, // std::vector<NotifyMotionArgs>, // std::vector<NotifySwitchArgs>> // mQueues GUARDED_BY(mLock); }; } // namespace android Loading