diff options
11 files changed, 65 insertions, 62 deletions
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp index 00dd6ba62b..31fbb515b2 100644 --- a/services/inputflinger/PointerChoreographer.cpp +++ b/services/inputflinger/PointerChoreographer.cpp @@ -202,6 +202,7 @@ void PointerChoreographer::fadeMouseCursorOnKeyPress(const android::NotifyKeyArg } auto it = mMousePointersByDisplay.find(targetDisplay); if (it != mMousePointersByDisplay.end()) { + mPolicy.notifyMouseCursorFadedOnTyping(); it->second->fade(PointerControllerInterface::Transition::GRADUAL); } } diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 889ee09e6f..42a03c10ca 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -397,6 +397,9 @@ public: * Returns ReservedInputDeviceId::INVALID_INPUT_DEVICE_ID if no device has been used since boot. */ virtual DeviceId getLastUsedInputDeviceId() = 0; + + /* Notifies that mouse cursor faded due to typing. */ + virtual void notifyMouseCursorFadedOnTyping() = 0; }; // --- TouchAffineTransformation --- diff --git a/services/inputflinger/include/PointerChoreographerPolicyInterface.h b/services/inputflinger/include/PointerChoreographerPolicyInterface.h index 7a85c12559..e1f8fdaaa0 100644 --- a/services/inputflinger/include/PointerChoreographerPolicyInterface.h +++ b/services/inputflinger/include/PointerChoreographerPolicyInterface.h @@ -58,6 +58,9 @@ public: /* Returns true if any InputConnection is currently active. */ virtual bool isInputMethodConnectionActive() = 0; + + /* Notifies that mouse cursor faded due to typing. */ + virtual void notifyMouseCursorFadedOnTyping() = 0; }; } // namespace android diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index ab13ad489b..0073fd1738 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -907,6 +907,12 @@ DeviceId InputReader::getLastUsedInputDeviceId() { return mLastUsedDeviceId; } +void InputReader::notifyMouseCursorFadedOnTyping() { + std::scoped_lock _l(mLock); + // disable touchpad taps when cursor has faded due to typing + mPreventingTouchpadTaps = true; +} + void InputReader::dump(std::string& dump) { std::scoped_lock _l(mLock); diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index 6f8c289093..03ca840b9f 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -118,6 +118,8 @@ public: DeviceId getLastUsedInputDeviceId() override; + void notifyMouseCursorFadedOnTyping() override; + protected: // These members are protected so they can be instrumented by test cases. virtual std::shared_ptr<InputDevice> createDeviceLocked(nsecs_t when, int32_t deviceId, @@ -199,7 +201,7 @@ private: std::unordered_map<std::shared_ptr<InputDevice>, std::vector<int32_t> /*eventHubId*/> mDeviceToEventHubIdsMap GUARDED_BY(mLock); - // true if tap-to-click on touchpad currently disabled + // true if tap-to-click on touchpad is currently disabled bool mPreventingTouchpadTaps GUARDED_BY(mLock){false}; // records timestamp of the last key press on the physical keyboard diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp index 25f4893baf..4a21e48f8f 100644 --- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp +++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp @@ -493,12 +493,6 @@ std::list<NotifyArgs> KeyboardInputMapper::cancelAllDownKeys(nsecs_t when) { void KeyboardInputMapper::onKeyDownProcessed(nsecs_t downTime) { InputReaderContext& context = *getContext(); context.setLastKeyDownTimestamp(downTime); - // Ignore meta keys or multiple simultaneous down keys as they are likely to be keyboard - // shortcuts - bool shouldHideCursor = mKeyDowns.size() == 1 && !isMetaKey(mKeyDowns[0].keyCode); - if (shouldHideCursor && context.getPolicy()->isInputMethodConnectionActive()) { - context.setPreventingTouchpadTaps(true); - } } } // namespace android diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index bacc6d432e..48e0b4f516 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -187,6 +187,7 @@ public: MOCK_METHOD(void, notifyPointerDisplayIdChanged, (ui::LogicalDisplayId displayId, const FloatPoint& position), (override)); MOCK_METHOD(bool, isInputMethodConnectionActive, (), (override)); + MOCK_METHOD(void, notifyMouseCursorFadedOnTyping, (), (override)); }; } // namespace android diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp index ab47cc67b1..d3e8dee4a0 100644 --- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp +++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp @@ -69,48 +69,8 @@ protected: mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration, AINPUT_SOURCE_KEYBOARD); } - - void testTouchpadTapStateForKeys(const std::vector<int32_t>& keyCodes, - const bool expectPrevent) { - if (expectPrevent) { - EXPECT_CALL(mMockInputReaderContext, setPreventingTouchpadTaps(true)) - .Times(keyCodes.size()); - } - for (int32_t keyCode : keyCodes) { - process(EV_KEY, keyCode, 1); - process(EV_SYN, SYN_REPORT, 0); - process(EV_KEY, keyCode, 0); - process(EV_SYN, SYN_REPORT, 0); - } - } }; -/** - * Touchpad tap should not be disabled if there is no active Input Method Connection - */ -TEST_F(KeyboardInputMapperUnitTest, KeystrokesWithoutIMeConnectionDontDisableTouchpadTap) { - testTouchpadTapStateForKeys({KEY_0, KEY_A, KEY_LEFTCTRL}, /* expectPrevent= */ false); -} - -/** - * Touchpad tap should be disabled if there is a active Input Method Connection - */ -TEST_F(KeyboardInputMapperUnitTest, AlphanumericKeystrokesWithIMeConnectionDisableTouchpadTap) { - mFakePolicy->setIsInputMethodConnectionActive(true); - testTouchpadTapStateForKeys({KEY_0, KEY_A}, /* expectPrevent= */ true); -} - -/** - * Touchpad tap should not be disabled by meta keys even if Input Method Connection is active - */ -TEST_F(KeyboardInputMapperUnitTest, MetaKeystrokesWithIMeConnectionDontDisableTouchpadTap) { - mFakePolicy->setIsInputMethodConnectionActive(true); - std::vector<int32_t> metaKeys{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTSHIFT, KEY_RIGHTSHIFT, - KEY_FN, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTMETA, - KEY_RIGHTMETA, KEY_CAPSLOCK, KEY_NUMLOCK, KEY_SCROLLLOCK}; - testTouchpadTapStateForKeys(metaKeys, /* expectPrevent= */ false); -} - TEST_F(KeyboardInputMapperUnitTest, KeyPressTimestampRecorded) { nsecs_t when = ARBITRARY_TIME; std::vector<int32_t> keyCodes{KEY_0, KEY_A, KEY_LEFTCTRL, KEY_RIGHTALT, KEY_LEFTSHIFT}; diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp index 9a5b6a73f5..144e723ecb 100644 --- a/services/inputflinger/tests/PointerChoreographer_test.cpp +++ b/services/inputflinger/tests/PointerChoreographer_test.cpp @@ -2294,7 +2294,13 @@ TEST_F(PointerChoreographerTest, MouseAndDrawingTabletReportMouseEvents) { assertPointerControllerRemoved(pc); } -class PointerVisibilityOnKeyPressTest : public PointerChoreographerTest { +using PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixtureParam = + std::tuple<std::string_view /*name*/, uint32_t /*source*/>; + +class PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixture + : public PointerChoreographerTest, + public testing::WithParamInterface< + PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixtureParam> { protected: const std::unordered_map<int32_t, int32_t> mMetaKeyStates{{AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON}, @@ -2358,15 +2364,28 @@ protected: } }; -TEST_F(PointerVisibilityOnKeyPressTest, KeystrokesWithoutImeConnectionDoesNotHidePointer) { +INSTANTIATE_TEST_SUITE_P( + PointerChoreographerTest, PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixture, + testing::Values(std::make_tuple("Mouse", AINPUT_SOURCE_MOUSE), + std::make_tuple("Touchpad", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD)), + [](const testing::TestParamInfo< + PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixtureParam>& p) { + return std::string{std::get<0>(p.param)}; + }); + +TEST_P(PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixture, + KeystrokesWithoutImeConnectionDoesNotHidePointerOrDisablesTouchpadTap) { + const auto& [_, source] = GetParam(); mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID})); // Mouse connected mChoreographer.notifyInputDevicesChanged( - {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID)}}); + {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, source, DISPLAY_ID)}}); auto pc = assertPointerControllerCreated(ControllerType::MOUSE); ASSERT_TRUE(pc->isPointerShown()); + EXPECT_CALL(mMockPolicy, notifyMouseCursorFadedOnTyping).Times(0); + notifyKey(ui::LogicalDisplayId::INVALID, AKEYCODE_0); notifyKey(ui::LogicalDisplayId::INVALID, AKEYCODE_A); notifyKey(ui::LogicalDisplayId::INVALID, AKEYCODE_CTRL_LEFT); @@ -2374,16 +2393,19 @@ TEST_F(PointerVisibilityOnKeyPressTest, KeystrokesWithoutImeConnectionDoesNotHid ASSERT_TRUE(pc->isPointerShown()); } -TEST_F(PointerVisibilityOnKeyPressTest, AlphanumericKeystrokesWithImeConnectionHidePointer) { +TEST_P(PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixture, + AlphanumericKeystrokesWithImeConnectionHidePointerAndDisablesTouchpadTap) { + const auto& [_, source] = GetParam(); mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID})); // Mouse connected mChoreographer.notifyInputDevicesChanged( - {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID)}}); + {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, source, DISPLAY_ID)}}); auto pc = assertPointerControllerCreated(ControllerType::MOUSE); ASSERT_TRUE(pc->isPointerShown()); EXPECT_CALL(mMockPolicy, isInputMethodConnectionActive).WillRepeatedly(testing::Return(true)); + EXPECT_CALL(mMockPolicy, notifyMouseCursorFadedOnTyping).Times(2); notifyKey(DISPLAY_ID, AKEYCODE_0); ASSERT_FALSE(pc->isPointerShown()); @@ -2394,17 +2416,19 @@ TEST_F(PointerVisibilityOnKeyPressTest, AlphanumericKeystrokesWithImeConnectionH ASSERT_FALSE(pc->isPointerShown()); } -TEST_F(PointerVisibilityOnKeyPressTest, MetaKeystrokesDoNotHidePointer) { +TEST_P(PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixture, + MetaKeystrokesDoNotHidePointerOrDisablesTouchpadTap) { + const auto& [_, source] = GetParam(); mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID})); // Mouse connected mChoreographer.notifyInputDevicesChanged( - {/*id=*/0, - {generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID)}}); + {/*id=*/0, {generateTestDeviceInfo(SECOND_DEVICE_ID, source, DISPLAY_ID)}}); auto pc = assertPointerControllerCreated(ControllerType::MOUSE); ASSERT_TRUE(pc->isPointerShown()); EXPECT_CALL(mMockPolicy, isInputMethodConnectionActive).WillRepeatedly(testing::Return(true)); + EXPECT_CALL(mMockPolicy, notifyMouseCursorFadedOnTyping).Times(0); const std::vector<int32_t> metaKeyCodes{AKEYCODE_ALT_LEFT, AKEYCODE_ALT_RIGHT, AKEYCODE_SHIFT_LEFT, AKEYCODE_SHIFT_RIGHT, @@ -2420,14 +2444,16 @@ TEST_F(PointerVisibilityOnKeyPressTest, MetaKeystrokesDoNotHidePointer) { ASSERT_TRUE(pc->isPointerShown()); } -TEST_F(PointerVisibilityOnKeyPressTest, KeystrokesWithoutTargetHidePointerOnlyOnFocusedDisplay) { +TEST_P(PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixture, + KeystrokesWithoutTargetHidePointerOnlyOnFocusedDisplayAndDisablesTouchpadTap) { + const auto& [_, source] = GetParam(); mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID})); mChoreographer.setFocusedDisplay(DISPLAY_ID); // Mouse connected mChoreographer.notifyInputDevicesChanged( {/*id=*/0, - {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID), + {generateTestDeviceInfo(DEVICE_ID, source, DISPLAY_ID), generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_MOUSE, ANOTHER_DISPLAY_ID)}}); auto pc1 = assertPointerControllerCreated(ControllerType::MOUSE); auto pc2 = assertPointerControllerCreated(ControllerType::MOUSE); @@ -2435,6 +2461,7 @@ TEST_F(PointerVisibilityOnKeyPressTest, KeystrokesWithoutTargetHidePointerOnlyOn ASSERT_TRUE(pc2->isPointerShown()); EXPECT_CALL(mMockPolicy, isInputMethodConnectionActive).WillRepeatedly(testing::Return(true)); + EXPECT_CALL(mMockPolicy, notifyMouseCursorFadedOnTyping).Times(2); notifyKey(ui::LogicalDisplayId::INVALID, AKEYCODE_0); ASSERT_FALSE(pc1->isPointerShown()); @@ -2446,16 +2473,19 @@ TEST_F(PointerVisibilityOnKeyPressTest, KeystrokesWithoutTargetHidePointerOnlyOn ASSERT_TRUE(pc2->isPointerShown()); } -TEST_F(PointerVisibilityOnKeyPressTest, TestMetaKeyCombinations) { +TEST_P(PointerVisibilityAndTouchpadTapStateOnKeyPressTestFixture, TestMetaKeyCombinations) { + const auto& [_, source] = GetParam(); mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID})); // Mouse connected mChoreographer.notifyInputDevicesChanged( - {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, DISPLAY_ID)}}); + {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, source, DISPLAY_ID)}}); auto pc = assertPointerControllerCreated(ControllerType::MOUSE); + EXPECT_CALL(mMockPolicy, isInputMethodConnectionActive).WillRepeatedly(testing::Return(true)); - // meta key combinations that should hide pointer + // meta key combinations that should hide pointer and disable touchpad taps + EXPECT_CALL(mMockPolicy, notifyMouseCursorFadedOnTyping).Times(5); metaKeyCombinationHidesPointer(*pc, AKEYCODE_A, AKEYCODE_SHIFT_LEFT); metaKeyCombinationHidesPointer(*pc, AKEYCODE_A, AKEYCODE_SHIFT_RIGHT); metaKeyCombinationHidesPointer(*pc, AKEYCODE_A, AKEYCODE_CAPS_LOCK); @@ -2463,6 +2493,7 @@ TEST_F(PointerVisibilityOnKeyPressTest, TestMetaKeyCombinations) { metaKeyCombinationHidesPointer(*pc, AKEYCODE_A, AKEYCODE_SCROLL_LOCK); // meta key combinations that should not hide pointer + EXPECT_CALL(mMockPolicy, notifyMouseCursorFadedOnTyping).Times(0); metaKeyCombinationDoesNotHidePointer(*pc, AKEYCODE_A, AKEYCODE_ALT_LEFT); metaKeyCombinationDoesNotHidePointer(*pc, AKEYCODE_A, AKEYCODE_ALT_RIGHT); metaKeyCombinationDoesNotHidePointer(*pc, AKEYCODE_A, AKEYCODE_CTRL_LEFT); diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp index 7d26a43440..d552c19532 100644 --- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp @@ -169,6 +169,8 @@ public: DeviceId getLastUsedInputDeviceId() override { return reader->getLastUsedInputDeviceId(); } + void notifyMouseCursorFadedOnTyping() override { reader->notifyMouseCursorFadedOnTyping(); } + private: std::unique_ptr<InputReaderInterface> reader; }; diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index 969c03268e..c4465b69cb 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -346,8 +346,8 @@ public: int32_t getLedMetaState() override { return mFdp->ConsumeIntegral<int32_t>(); }; void notifyStylusGestureStarted(int32_t, nsecs_t) {} - void setPreventingTouchpadTaps(bool prevent) {} - bool isPreventingTouchpadTaps() { return mFdp->ConsumeBool(); }; + void setPreventingTouchpadTaps(bool prevent) override {} + bool isPreventingTouchpadTaps() override { return mFdp->ConsumeBool(); }; void setLastKeyDownTimestamp(nsecs_t when) { mLastKeyDownTimestamp = when; }; nsecs_t getLastKeyDownTimestamp() { return mLastKeyDownTimestamp; }; |