Loading services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ uint32_t ExternalStylusInputMapper::getSources() const { void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo& info) { InputMapper::populateDeviceInfo(info); if (mRawPressureAxis) { if (mRawPressureAxis || mTouchButtonAccumulator.hasButtonTouch()) { info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); } Loading services/inputflinger/reader/mapper/TouchInputMapper.cpp +18 −7 Original line number Diff line number Diff line Loading @@ -149,7 +149,10 @@ uint32_t TouchInputMapper::getSources() const { // The SOURCE_BLUETOOTH_STYLUS is added to events dynamically if the current stream is modified // by the external stylus state. That's why we don't add it directly to mSource during // configuration. return mSource | (hasExternalStylus() ? AINPUT_SOURCE_BLUETOOTH_STYLUS : 0); return mSource | (mExternalStylusPresence == ExternalStylusPresence::TOUCH_FUSION ? AINPUT_SOURCE_BLUETOOTH_STYLUS : 0); } void TouchInputMapper::populateDeviceInfo(InputDeviceInfo& info) { Loading Loading @@ -270,8 +273,8 @@ void TouchInputMapper::dump(std::string& dump) { } dump += INDENT3 "Stylus Fusion:\n"; dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n", toString(mExternalStylusConnected)); dump += StringPrintf(INDENT4 "ExternalStylusPresence: %s\n", ftl::enum_string(mExternalStylusPresence).c_str()); dump += StringPrintf(INDENT4 "Fused External Stylus Pointer ID: %s\n", toString(mFusedStylusPointerId).c_str()); dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n", Loading Loading @@ -356,11 +359,19 @@ std::list<NotifyArgs> TouchInputMapper::reconfigure(nsecs_t when, void TouchInputMapper::resolveExternalStylusPresence() { std::vector<InputDeviceInfo> devices; getContext()->getExternalStylusDevices(devices); mExternalStylusConnected = !devices.empty(); if (!mExternalStylusConnected) { if (devices.empty()) { mExternalStylusPresence = ExternalStylusPresence::NONE; resetExternalStylus(); return; } mExternalStylusPresence = std::any_of(devices.begin(), devices.end(), [](const auto& info) { return info.getMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS) != nullptr; }) ? ExternalStylusPresence::TOUCH_FUSION : ExternalStylusPresence::BUTTON_FUSION; } TouchInputMapper::Parameters TouchInputMapper::computeParameters( Loading Loading @@ -520,7 +531,7 @@ void TouchInputMapper::dumpRawPointerAxes(std::string& dump) { } bool TouchInputMapper::hasExternalStylus() const { return mExternalStylusConnected; return mExternalStylusPresence != ExternalStylusPresence::NONE; } /** Loading services/inputflinger/reader/mapper/TouchInputMapper.h +10 −2 Original line number Diff line number Diff line Loading @@ -365,6 +365,16 @@ protected: RawState mLastRawState; CookedState mLastCookedState; enum class ExternalStylusPresence { // No external stylus connected. NONE, // An external stylus that can report touch/pressure that can be fused with the touchscreen. TOUCH_FUSION, // An external stylus that can only report buttons. BUTTON_FUSION, ftl_last = BUTTON_FUSION, }; ExternalStylusPresence mExternalStylusPresence{ExternalStylusPresence::NONE}; // State provided by an external stylus StylusState mExternalStylusState; // If an external stylus is capable of reporting pointer-specific data like pressure, we will Loading Loading @@ -460,8 +470,6 @@ private: float mTiltYCenter; float mTiltYScale; bool mExternalStylusConnected; // Oriented motion ranges for input device info. struct OrientedRanges { InputDeviceInfo::MotionRange x; Loading services/inputflinger/tests/InputReader_test.cpp +21 −3 Original line number Diff line number Diff line Loading @@ -6675,15 +6675,27 @@ INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFix class ExternalStylusFusionTest : public SingleTouchInputMapperTest { public: SingleTouchInputMapper& initializeInputMapperWithExternalStylus() { void SetUp() override { SingleTouchInputMapperTest::SetUp(); mExternalStylusDeviceInfo = {}; mStylusState = {}; } SingleTouchInputMapper& initializeInputMapperWithExternalStylus(bool supportsPressure = true) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(ui::ROTATION_0); prepareButtons(); prepareAxes(POSITION); auto& mapper = constructAndAddMapper<SingleTouchInputMapper>(); mStylusState.when = ARBITRARY_TIME; if (supportsPressure) { mExternalStylusDeviceInfo.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); mStylusState.pressure = 0.f; } mStylusState.when = ARBITRARY_TIME; mStylusState.toolType = ToolType::STYLUS; mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo}); configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE); Loading Loading @@ -6791,11 +6803,17 @@ private: InputDeviceInfo mExternalStylusDeviceInfo{}; }; TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) { TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSourceWithPressure) { SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus(); ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources()); } TEST_F(ExternalStylusFusionTest, DoesNotUseBluetoothStylusSourceWithoutPressure) { SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus(/*supportsPressure=*/false); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources()); } TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) { SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus(); ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper)); Loading Loading
services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ uint32_t ExternalStylusInputMapper::getSources() const { void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo& info) { InputMapper::populateDeviceInfo(info); if (mRawPressureAxis) { if (mRawPressureAxis || mTouchButtonAccumulator.hasButtonTouch()) { info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); } Loading
services/inputflinger/reader/mapper/TouchInputMapper.cpp +18 −7 Original line number Diff line number Diff line Loading @@ -149,7 +149,10 @@ uint32_t TouchInputMapper::getSources() const { // The SOURCE_BLUETOOTH_STYLUS is added to events dynamically if the current stream is modified // by the external stylus state. That's why we don't add it directly to mSource during // configuration. return mSource | (hasExternalStylus() ? AINPUT_SOURCE_BLUETOOTH_STYLUS : 0); return mSource | (mExternalStylusPresence == ExternalStylusPresence::TOUCH_FUSION ? AINPUT_SOURCE_BLUETOOTH_STYLUS : 0); } void TouchInputMapper::populateDeviceInfo(InputDeviceInfo& info) { Loading Loading @@ -270,8 +273,8 @@ void TouchInputMapper::dump(std::string& dump) { } dump += INDENT3 "Stylus Fusion:\n"; dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n", toString(mExternalStylusConnected)); dump += StringPrintf(INDENT4 "ExternalStylusPresence: %s\n", ftl::enum_string(mExternalStylusPresence).c_str()); dump += StringPrintf(INDENT4 "Fused External Stylus Pointer ID: %s\n", toString(mFusedStylusPointerId).c_str()); dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n", Loading Loading @@ -356,11 +359,19 @@ std::list<NotifyArgs> TouchInputMapper::reconfigure(nsecs_t when, void TouchInputMapper::resolveExternalStylusPresence() { std::vector<InputDeviceInfo> devices; getContext()->getExternalStylusDevices(devices); mExternalStylusConnected = !devices.empty(); if (!mExternalStylusConnected) { if (devices.empty()) { mExternalStylusPresence = ExternalStylusPresence::NONE; resetExternalStylus(); return; } mExternalStylusPresence = std::any_of(devices.begin(), devices.end(), [](const auto& info) { return info.getMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS) != nullptr; }) ? ExternalStylusPresence::TOUCH_FUSION : ExternalStylusPresence::BUTTON_FUSION; } TouchInputMapper::Parameters TouchInputMapper::computeParameters( Loading Loading @@ -520,7 +531,7 @@ void TouchInputMapper::dumpRawPointerAxes(std::string& dump) { } bool TouchInputMapper::hasExternalStylus() const { return mExternalStylusConnected; return mExternalStylusPresence != ExternalStylusPresence::NONE; } /** Loading
services/inputflinger/reader/mapper/TouchInputMapper.h +10 −2 Original line number Diff line number Diff line Loading @@ -365,6 +365,16 @@ protected: RawState mLastRawState; CookedState mLastCookedState; enum class ExternalStylusPresence { // No external stylus connected. NONE, // An external stylus that can report touch/pressure that can be fused with the touchscreen. TOUCH_FUSION, // An external stylus that can only report buttons. BUTTON_FUSION, ftl_last = BUTTON_FUSION, }; ExternalStylusPresence mExternalStylusPresence{ExternalStylusPresence::NONE}; // State provided by an external stylus StylusState mExternalStylusState; // If an external stylus is capable of reporting pointer-specific data like pressure, we will Loading Loading @@ -460,8 +470,6 @@ private: float mTiltYCenter; float mTiltYScale; bool mExternalStylusConnected; // Oriented motion ranges for input device info. struct OrientedRanges { InputDeviceInfo::MotionRange x; Loading
services/inputflinger/tests/InputReader_test.cpp +21 −3 Original line number Diff line number Diff line Loading @@ -6675,15 +6675,27 @@ INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFix class ExternalStylusFusionTest : public SingleTouchInputMapperTest { public: SingleTouchInputMapper& initializeInputMapperWithExternalStylus() { void SetUp() override { SingleTouchInputMapperTest::SetUp(); mExternalStylusDeviceInfo = {}; mStylusState = {}; } SingleTouchInputMapper& initializeInputMapperWithExternalStylus(bool supportsPressure = true) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(ui::ROTATION_0); prepareButtons(); prepareAxes(POSITION); auto& mapper = constructAndAddMapper<SingleTouchInputMapper>(); mStylusState.when = ARBITRARY_TIME; if (supportsPressure) { mExternalStylusDeviceInfo.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); mStylusState.pressure = 0.f; } mStylusState.when = ARBITRARY_TIME; mStylusState.toolType = ToolType::STYLUS; mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo}); configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE); Loading Loading @@ -6791,11 +6803,17 @@ private: InputDeviceInfo mExternalStylusDeviceInfo{}; }; TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) { TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSourceWithPressure) { SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus(); ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources()); } TEST_F(ExternalStylusFusionTest, DoesNotUseBluetoothStylusSourceWithoutPressure) { SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus(/*supportsPressure=*/false); ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources()); } TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) { SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus(); ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper)); Loading