diff options
4 files changed, 34 insertions, 15 deletions
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp index ccff353824..b193dffcfc 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp @@ -119,6 +119,18 @@ void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) { outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; } + } else if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS && !mStylusMtToolSeen) { + mStylusMtToolSeen = true; + // The multi-touch device produced a stylus event with MT_TOOL_PEN. Dynamically + // re-configure this input device so that we add SOURCE_STYLUS if we haven't already. + // This is to cover the case where we cannot reliably detect whether a multi-touch + // device will ever produce stylus events when it is initially being configured. + if (!isFromSource(mSource, AINPUT_SOURCE_STYLUS)) { + // Add the stylus source immediately so that it is included in any events generated + // before we have a chance to re-configure the device. + mSource |= AINPUT_SOURCE_STYLUS; + bumpGeneration(); + } } if (shouldSimulateStylusWithTouch() && outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER) { @@ -200,7 +212,8 @@ void MultiTouchInputMapper::configureRawPointerAxes() { } bool MultiTouchInputMapper::hasStylus() const { - return mTouchButtonAccumulator.hasStylus() || shouldSimulateStylusWithTouch(); + return mStylusMtToolSeen || mTouchButtonAccumulator.hasStylus() || + shouldSimulateStylusWithTouch(); } bool MultiTouchInputMapper::shouldSimulateStylusWithTouch() const { diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h index ddf9e80a6c..5f8bccf9e6 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h @@ -50,6 +50,8 @@ private: // Specifies the pointer id bits that are in use, and their associated tracking id. BitSet32 mPointerIdBits; int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1]; + + bool mStylusMtToolSeen{false}; }; } // namespace android diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index bc55fe5922..5be694f35f 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -3763,15 +3763,12 @@ NotifyMotionArgs TouchInputMapper::dispatchMotion( PointerCoords pointerCoords[MAX_POINTERS]; PointerProperties pointerProperties[MAX_POINTERS]; uint32_t pointerCount = 0; - bool stylusToolFound = false; while (!idBits.isEmpty()) { uint32_t id = idBits.clearFirstMarkedBit(); uint32_t index = idToIndex[id]; pointerProperties[pointerCount].copyFrom(properties[index]); pointerCoords[pointerCount].copyFrom(coords[index]); - stylusToolFound |= isStylusToolType(pointerProperties[pointerCount].toolType); - if (changedId >= 0 && id == uint32_t(changedId)) { action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; } @@ -3803,12 +3800,6 @@ NotifyMotionArgs TouchInputMapper::dispatchMotion( if (mDeviceMode == DeviceMode::POINTER) { mPointerController->getPosition(&xCursorPosition, &yCursorPosition); } - if (stylusToolFound) { - // Dynamically add the stylus source when there's a stylus tool being used to cover the case - // where we cannot reliably detect whether a multi-touch device will ever produce stylus - // events when it is initially being configured. - source |= AINPUT_SOURCE_STYLUS; - } const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE); const int32_t deviceId = getDeviceId(); std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames(); diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 5c5fc77ea9..6b6d0bbfaa 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -10788,11 +10788,12 @@ TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); } -TEST_F(MultiTouchInputMapperTest, ToolTypeSource) { +TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) { addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled()); // Even if the device supports reporting the ABS_MT_TOOL_TYPE axis, which could give it the // ability to report MT_TOOL_PEN, we do not report the device as coming from a stylus source. @@ -10801,7 +10802,7 @@ TEST_F(MultiTouchInputMapperTest, ToolTypeSource) { ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources()); // However, if the device ever ends up reporting an event with MT_TOOL_PEN, it should be - // reported with the stylus source, even through the device doesn't support the stylus source. + // reported with the stylus source. processId(mapper, FIRST_TRACKING_ID); processToolType(mapper, MT_TOOL_PEN); processPosition(mapper, 100, 200); @@ -10812,15 +10813,27 @@ TEST_F(MultiTouchInputMapperTest, ToolTypeSource) { WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS), WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS)))); + // Now that we know the device supports styluses, ensure that the device is re-configured with + // the stylus source. + ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, mapper.getSources()); + { + const auto& devices = mReader->getInputDevices(); + auto deviceInfo = + std::find_if(devices.begin(), devices.end(), + [](const InputDeviceInfo& info) { return info.getId() == DEVICE_ID; }); + LOG_ALWAYS_FATAL_IF(deviceInfo == devices.end(), "Cannot find InputDevice"); + ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, deviceInfo->getSources()); + } + + // Ensure the device was not reset to prevent interruptions of any ongoing gestures. + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled()); + processId(mapper, INVALID_TRACKING_ID); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled( AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS), WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS)))); - - // The mapper should still report only a touchscreen source. - ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources()); } // --- MultiTouchInputMapperTest_ExternalDevice --- |