Loading services/inputflinger/reader/include/InputDevice.h +1 −0 Original line number Diff line number Diff line Loading @@ -299,6 +299,7 @@ public: inline ftl::Flags<InputDeviceClass> getDeviceClasses() const { return mEventHub->getDeviceClasses(mId); } inline uint32_t getDeviceSources() const { return mDevice.getSources(); } inline InputDeviceIdentifier getDeviceIdentifier() const { return mEventHub->getDeviceIdentifier(mId); } Loading services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +20 −10 Original line number Diff line number Diff line Loading @@ -98,10 +98,10 @@ static bool isMediaKey(int32_t keyCode) { KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig, uint32_t source) : InputMapper(deviceContext, readerConfig), mSource(source) {} : InputMapper(deviceContext, readerConfig), mMapperSource(source) {} uint32_t KeyboardInputMapper::getSources() const { return mSource; return mMapperSource; } ui::Rotation KeyboardInputMapper::getOrientation() { Loading Loading @@ -351,8 +351,8 @@ std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t read policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT; } out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, deviceId, mSource, getDisplayId(), policyFlags, out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, deviceId, getEventSource(), getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, flags, keyCode, scanCode, keyMetaState, downTime)); return out; Loading Loading @@ -478,10 +478,10 @@ std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) { std::list<NotifyArgs> out; size_t n = mKeyDowns.size(); for (size_t i = 0; i < n; i++) { out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource, getDisplayId(), /*policyFlags=*/0, AKEY_EVENT_ACTION_UP, mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED, out.emplace_back( NotifyKeyArgs(getContext()->getNextId(), when, systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), getEventSource(), getDisplayId(), /*policyFlags=*/0, AKEY_EVENT_ACTION_UP, mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED, mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE, mKeyDowns[i].downTime)); } Loading @@ -495,4 +495,14 @@ void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) { context.setLastKeyDownTimestamp(downTime); } uint32_t KeyboardInputMapper::getEventSource() const { // For all input events generated by this mapper, use the source that's shared across all // KeyboardInputMappers for this device in case there are more than one. static constexpr auto ALL_KEYBOARD_SOURCES = AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD; const auto deviceSources = getDeviceContext().getDeviceSources(); LOG_ALWAYS_FATAL_IF((deviceSources & mMapperSource) != mMapperSource); return deviceSources & ALL_KEYBOARD_SOURCES; } } // namespace android services/inputflinger/reader/mapper/KeyboardInputMapper.h +5 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,10 @@ private: int32_t flags{}; }; uint32_t mSource{}; // The keyboard source for this mapper. Events generated should use the source shared // by all KeyboardInputMappers for this input device. uint32_t mMapperSource{}; std::optional<KeyboardLayoutInfo> mKeyboardLayoutInfo; std::vector<KeyDown> mKeyDowns{}; // keys that are down Loading Loading @@ -106,6 +109,7 @@ private: std::optional<DisplayViewport> findViewport(const InputReaderConfiguration& readerConfig); [[nodiscard]] std::list<NotifyArgs> cancelAllDownKeys(nsecs_t when); void onKeyDownProcessed(nsecs_t downTime); uint32_t getEventSource() const; }; } // namespace android services/inputflinger/tests/InputMapperTest.h +5 −4 Original line number Diff line number Diff line Loading @@ -116,11 +116,12 @@ protected: T& constructAndAddMapper(Args... args) { // ensure a device entry exists for this eventHubId mDevice->addEmptyEventHubDevice(EVENTHUB_ID); // configure the empty device configureDevice(/*changes=*/{}); return mDevice->constructAndAddMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), args...); auto& mapper = mDevice->constructAndAddMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), args...); configureDevice(/*changes=*/{}); return mapper; } void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height, Loading services/inputflinger/tests/InputReader_test.cpp +45 −0 Original line number Diff line number Diff line Loading @@ -4039,6 +4039,51 @@ TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) { ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags); } /** * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce * events that use the shared keyboard source across all mappers. This is to ensure that each * input device generates key events in a consistent manner, regardless of which mapper produces * the event. */ TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) { mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE); // Add a mapper with SOURCE_KEYBOARD KeyboardInputMapper& keyboardMapper = constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD); process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); ASSERT_NO_FATAL_FAILURE( mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD))); process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE( mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD))); // Add a mapper with SOURCE_DPAD KeyboardInputMapper& dpadMapper = constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD); for (auto* mapper : {&keyboardMapper, &dpadMapper}) { process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD))); process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD))); } // Add a mapper with SOURCE_GAMEPAD KeyboardInputMapper& gamepadMapper = constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD); for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) { process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD))); process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD))); } } // --- KeyboardInputMapperTest_ExternalAlphabeticDevice --- class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest { Loading Loading
services/inputflinger/reader/include/InputDevice.h +1 −0 Original line number Diff line number Diff line Loading @@ -299,6 +299,7 @@ public: inline ftl::Flags<InputDeviceClass> getDeviceClasses() const { return mEventHub->getDeviceClasses(mId); } inline uint32_t getDeviceSources() const { return mDevice.getSources(); } inline InputDeviceIdentifier getDeviceIdentifier() const { return mEventHub->getDeviceIdentifier(mId); } Loading
services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +20 −10 Original line number Diff line number Diff line Loading @@ -98,10 +98,10 @@ static bool isMediaKey(int32_t keyCode) { KeyboardInputMapper::KeyboardInputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig, uint32_t source) : InputMapper(deviceContext, readerConfig), mSource(source) {} : InputMapper(deviceContext, readerConfig), mMapperSource(source) {} uint32_t KeyboardInputMapper::getSources() const { return mSource; return mMapperSource; } ui::Rotation KeyboardInputMapper::getOrientation() { Loading Loading @@ -351,8 +351,8 @@ std::list<NotifyArgs> KeyboardInputMapper::processKey(nsecs_t when, nsecs_t read policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT; } out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, deviceId, mSource, getDisplayId(), policyFlags, out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, readTime, deviceId, getEventSource(), getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, flags, keyCode, scanCode, keyMetaState, downTime)); return out; Loading Loading @@ -478,10 +478,10 @@ std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) { std::list<NotifyArgs> out; size_t n = mKeyDowns.size(); for (size_t i = 0; i < n; i++) { out.emplace_back(NotifyKeyArgs(getContext()->getNextId(), when, systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), mSource, getDisplayId(), /*policyFlags=*/0, AKEY_EVENT_ACTION_UP, mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED, out.emplace_back( NotifyKeyArgs(getContext()->getNextId(), when, systemTime(SYSTEM_TIME_MONOTONIC), getDeviceId(), getEventSource(), getDisplayId(), /*policyFlags=*/0, AKEY_EVENT_ACTION_UP, mKeyDowns[i].flags | AKEY_EVENT_FLAG_CANCELED, mKeyDowns[i].keyCode, mKeyDowns[i].scanCode, AMETA_NONE, mKeyDowns[i].downTime)); } Loading @@ -495,4 +495,14 @@ void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) { context.setLastKeyDownTimestamp(downTime); } uint32_t KeyboardInputMapper::getEventSource() const { // For all input events generated by this mapper, use the source that's shared across all // KeyboardInputMappers for this device in case there are more than one. static constexpr auto ALL_KEYBOARD_SOURCES = AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD; const auto deviceSources = getDeviceContext().getDeviceSources(); LOG_ALWAYS_FATAL_IF((deviceSources & mMapperSource) != mMapperSource); return deviceSources & ALL_KEYBOARD_SOURCES; } } // namespace android
services/inputflinger/reader/mapper/KeyboardInputMapper.h +5 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,10 @@ private: int32_t flags{}; }; uint32_t mSource{}; // The keyboard source for this mapper. Events generated should use the source shared // by all KeyboardInputMappers for this input device. uint32_t mMapperSource{}; std::optional<KeyboardLayoutInfo> mKeyboardLayoutInfo; std::vector<KeyDown> mKeyDowns{}; // keys that are down Loading Loading @@ -106,6 +109,7 @@ private: std::optional<DisplayViewport> findViewport(const InputReaderConfiguration& readerConfig); [[nodiscard]] std::list<NotifyArgs> cancelAllDownKeys(nsecs_t when); void onKeyDownProcessed(nsecs_t downTime); uint32_t getEventSource() const; }; } // namespace android
services/inputflinger/tests/InputMapperTest.h +5 −4 Original line number Diff line number Diff line Loading @@ -116,11 +116,12 @@ protected: T& constructAndAddMapper(Args... args) { // ensure a device entry exists for this eventHubId mDevice->addEmptyEventHubDevice(EVENTHUB_ID); // configure the empty device configureDevice(/*changes=*/{}); return mDevice->constructAndAddMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), args...); auto& mapper = mDevice->constructAndAddMapper<T>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(), args...); configureDevice(/*changes=*/{}); return mapper; } void setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width, int32_t height, Loading
services/inputflinger/tests/InputReader_test.cpp +45 −0 Original line number Diff line number Diff line Loading @@ -4039,6 +4039,51 @@ TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) { ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags); } /** * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce * events that use the shared keyboard source across all mappers. This is to ensure that each * input device generates key events in a consistent manner, regardless of which mapper produces * the event. */ TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) { mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE); // Add a mapper with SOURCE_KEYBOARD KeyboardInputMapper& keyboardMapper = constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD); process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); ASSERT_NO_FATAL_FAILURE( mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD))); process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE( mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD))); // Add a mapper with SOURCE_DPAD KeyboardInputMapper& dpadMapper = constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD); for (auto* mapper : {&keyboardMapper, &dpadMapper}) { process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD))); process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD))); } // Add a mapper with SOURCE_GAMEPAD KeyboardInputMapper& gamepadMapper = constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD); for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) { process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD))); process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled( WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD))); } } // --- KeyboardInputMapperTest_ExternalAlphabeticDevice --- class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest { Loading