Dynamically add STYLUS source for multi-touch devices
Since we cannot tell definitively whether a multi-touch device that
supports MT_TOOL_TYPE will ever report MT_TOOL_PEN, we default to
configuring the source of such a device not not use SOURCE_STYLUS, and
it to events dynamically if it ever produces a stylus event.
Bug: 246991366
Test: atest inputflinger_tests
Change-Id: I70cc15f8f354e3fc876024d194a6f320fabd6d2c
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index 8e757a5..ccff353 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -200,8 +200,7 @@
}
bool MultiTouchInputMapper::hasStylus() const {
- return mMultiTouchMotionAccumulator.hasStylus() || mTouchButtonAccumulator.hasStylus() ||
- shouldSimulateStylusWithTouch();
+ return mTouchButtonAccumulator.hasStylus() || shouldSimulateStylusWithTouch();
}
bool MultiTouchInputMapper::shouldSimulateStylusWithTouch() const {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 7db73db..e8fcdc8 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -3759,12 +3759,15 @@
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;
}
@@ -3796,6 +3799,12 @@
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/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
index b0cef67..8746729 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
@@ -24,12 +24,11 @@
// --- MultiTouchMotionAccumulator ---
MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
- : mCurrentSlot(-1), mUsingSlotsProtocol(false), mHaveStylus(false) {}
+ : mCurrentSlot(-1), mUsingSlotsProtocol(false) {}
void MultiTouchMotionAccumulator::configure(InputDeviceContext& deviceContext, size_t slotCount,
bool usingSlotsProtocol) {
mUsingSlotsProtocol = usingSlotsProtocol;
- mHaveStylus = deviceContext.hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
mSlots = std::vector<Slot>(slotCount);
mCurrentSlot = -1;
@@ -146,10 +145,6 @@
}
}
-bool MultiTouchMotionAccumulator::hasStylus() const {
- return mHaveStylus;
-}
-
void MultiTouchMotionAccumulator::warnIfNotInUse(const RawEvent& event, const Slot& slot) {
if (!slot.mInUse) {
ALOGW("Received unexpected event (0x%0x, 0x%0x) for slot %i with tracking id %i",
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
index 625a00f..62bc780 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
@@ -75,7 +75,6 @@
void configure(InputDeviceContext& deviceContext, size_t slotCount, bool usingSlotsProtocol);
void process(const RawEvent* rawEvent);
void finishSync();
- bool hasStylus() const;
inline size_t getSlotCount() const { return mSlots.size(); }
inline const Slot& getSlot(size_t index) const {
@@ -87,7 +86,6 @@
int32_t mCurrentSlot;
std::vector<Slot> mSlots;
bool mUsingSlotsProtocol;
- bool mHaveStylus;
void resetSlots();
void warnIfNotInUse(const RawEvent& event, const Slot& slot);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 3ce03f3..461fd5d 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -2571,6 +2571,14 @@
InputDeviceInfo mDeviceInfo;
};
+TEST_F(TouchIntegrationTest, MultiTouchDeviceSource) {
+ // The UinputTouchScreen is an MT device that supports MT_TOOL_TYPE and also supports stylus
+ // buttons. It should show up as a touchscreen, stylus, and keyboard (for reporting button
+ // presses).
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD,
+ mDeviceInfo.getSources());
+}
+
TEST_F(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
NotifyMotionArgs args;
const Point centerPoint = mDevice->getCenterPoint();
@@ -10671,6 +10679,41 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
}
+TEST_F(MultiTouchInputMapperTest, ToolTypeSource) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // 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.
+ // Due to limitations in the evdev protocol, we cannot say for certain that a device is capable
+ // of reporting stylus events just because it supports ABS_MT_TOOL_TYPE.
+ 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.
+ processId(mapper, FIRST_TRACKING_ID);
+ processToolType(mapper, MT_TOOL_PEN);
+ processPosition(mapper, 100, 200);
+ processPressure(mapper, RAW_PRESSURE_MAX);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
+ WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
+ WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
+
+ 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 ---
class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {