summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArpit Singh <arpitks@google.com>2023-12-20 14:41:10 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-20 18:37:14 +0000
commitc0749b449bb91f4a7d3356a9553aa5f71c0db24a (patch)
treeff24e7e2d0fe1410b06341972e054f4381a1436e
parent8a40509f77e0a410e9f30a60e68a481862f0bfcb (diff)
downloadnative-c0749b449bb91f4a7d3356a9553aa5f71c0db24a.tar.gz
Revert "InputReader: Clear the multi-touch state when the device is reset"
This reverts commit f8d9e440558f4dfb13ef41e23f41f30092297582. Reason for revert: b/316593362 Test: atest inputflinger_tests Bug: b/316593362 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4bb0bd5eb22f87c7c39a982bc4a7e6826f224383) Merged-In: Idfbf2091febba12c0e92a39bedb56b1058b85047 Change-Id: Idfbf2091febba12c0e92a39bedb56b1058b85047
-rw-r--r--services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp10
-rw-r--r--services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp38
-rw-r--r--services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h1
-rw-r--r--services/inputflinger/tests/InputReader_test.cpp87
4 files changed, 30 insertions, 106 deletions
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index 5a74a42446..2dd05f5c66 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -35,10 +35,12 @@ MultiTouchInputMapper::MultiTouchInputMapper(InputDeviceContext& deviceContext,
MultiTouchInputMapper::~MultiTouchInputMapper() {}
std::list<NotifyArgs> MultiTouchInputMapper::reset(nsecs_t when) {
- // TODO(b/291626046): Sync the MT state with the kernel using EVIOCGMTSLOTS.
- mMultiTouchMotionAccumulator.reset(getDeviceContext());
- mPointerIdBits.clear();
-
+ // The evdev multi-touch protocol does not allow userspace applications to query the initial or
+ // current state of the pointers at any time. This means if we clear our accumulated state when
+ // resetting the input mapper, there's no way to rebuild the full initial state of the pointers.
+ // We can only wait for updates to all the pointers and axes. Rather than clearing the state and
+ // rebuilding the state from scratch, we work around this kernel API limitation by never
+ // fully clearing any state specific to the multi-touch protocol.
return TouchInputMapper::reset(when);
}
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
index d06514acab..b0fc9035f2 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp
@@ -30,29 +30,23 @@ void MultiTouchMotionAccumulator::configure(const InputDeviceContext& deviceCont
size_t slotCount, bool usingSlotsProtocol) {
mUsingSlotsProtocol = usingSlotsProtocol;
mSlots = std::vector<Slot>(slotCount);
- reset(deviceContext);
-}
-
-void MultiTouchMotionAccumulator::reset(const InputDeviceContext& deviceContext) {
- resetSlots();
-
- if (!mUsingSlotsProtocol) {
- return;
- }
- // Query the driver for the current slot index and use it as the initial slot before we
- // start reading events from the device. It is possible that the current slot index will
- // not be the same as it was when the first event was written into the evdev buffer, which
- // means the input mapper could start out of sync with the initial state of the events in
- // the evdev buffer. In the extremely unlikely case that this happens, the data from two
- // slots will be confused until the next ABS_MT_SLOT event is received. This can cause the
- // touch point to "jump", but at least there will be no stuck touches.
- int32_t initialSlot;
- if (const auto status = deviceContext.getAbsoluteAxisValue(ABS_MT_SLOT, &initialSlot);
- status == OK) {
- mCurrentSlot = initialSlot;
- } else {
- ALOGD("Could not retrieve current multi-touch slot index. status=%d", status);
+ mCurrentSlot = -1;
+ if (mUsingSlotsProtocol) {
+ // Query the driver for the current slot index and use it as the initial slot before we
+ // start reading events from the device. It is possible that the current slot index will
+ // not be the same as it was when the first event was written into the evdev buffer, which
+ // means the input mapper could start out of sync with the initial state of the events in
+ // the evdev buffer. In the extremely unlikely case that this happens, the data from two
+ // slots will be confused until the next ABS_MT_SLOT event is received. This can cause the
+ // touch point to "jump", but at least there will be no stuck touches.
+ int32_t initialSlot;
+ if (const auto status = deviceContext.getAbsoluteAxisValue(ABS_MT_SLOT, &initialSlot);
+ status == OK) {
+ mCurrentSlot = initialSlot;
+ } else {
+ ALOGD("Could not retrieve current multi-touch slot index. status=%d", status);
+ }
}
}
diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
index 5b55e3d599..0e3e2bb365 100644
--- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.h
@@ -83,7 +83,6 @@ public:
LOG_ALWAYS_FATAL_IF(index < 0 || index >= mSlots.size(), "Invalid index: %zu", index);
return mSlots[index];
}
- void reset(const InputDeviceContext& deviceContext);
private:
int32_t mCurrentSlot;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index e0a3e94aad..faf7012c08 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -10971,7 +10971,7 @@ TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
ASSERT_EQ(uint32_t(1), motionArgs.getPointerCount());
}
-TEST_F(MultiTouchInputMapperTest, ResetClearsTouchState) {
+TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
@@ -10994,36 +10994,25 @@ TEST_F(MultiTouchInputMapperTest, ResetClearsTouchState) {
ASSERT_NO_FATAL_FAILURE(
mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
- // Reset the mapper. When the mapper is reset, the touch state is also cleared.
+ // Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
+ // preserved. Resetting should cancel the ongoing gesture.
resetMapper(mapper, ARBITRARY_TIME);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
- // Move the second slot pointer, and ensure there are no events, because the touch state was
- // cleared and no slots should be in use.
+ // Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
+ // the existing touch state to generate a down event.
processPosition(mapper, 301, 302);
processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-
- // Release both fingers.
- processId(mapper, INVALID_TRACKING_ID);
- processSlot(mapper, FIRST_SLOT);
- processId(mapper, INVALID_TRACKING_ID);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-
- // Start a new gesture, and ensure we get a DOWN event for it.
- processId(mapper, FIRST_TRACKING_ID);
- processPosition(mapper, 200, 300);
- processPressure(mapper, RAW_PRESSURE_MAX);
- processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithPressure(1.f))));
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithMotionAction(ACTION_POINTER_1_DOWN), WithPressure(1.f))));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
}
-TEST_F(MultiTouchInputMapperTest, ResetClearsTouchStateWithNoPointersDown) {
+TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
@@ -11151,66 +11140,6 @@ TEST_F(MultiTouchInputMapperTest, Process_WhenConfigDisabled_ShouldNotShowDirect
ASSERT_FALSE(fakePointerController->isPointerShown());
}
-TEST_F(MultiTouchInputMapperTest, SimulateKernelBufferOverflow) {
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(ui::ROTATION_0);
- prepareAxes(POSITION | ID | SLOT | PRESSURE);
- MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
-
- // First finger down.
- processId(mapper, FIRST_TRACKING_ID);
- processPosition(mapper, 100, 200);
- processPressure(mapper, RAW_PRESSURE_MAX);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
- WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
-
- // Assume the kernel buffer overflows, and we get a SYN_DROPPED event.
- // This will reset the mapper, and thus also reset the touch state.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_DROPPED, 0);
- resetMapper(mapper, ARBITRARY_TIME);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
- WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
-
- // Since the touch state was reset, it doesn't know which slots are active, so any movements
- // are ignored.
- processPosition(mapper, 101, 201);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-
- // Second finger goes down. This is the first active finger, so we get a DOWN event.
- processSlot(mapper, SECOND_SLOT);
- processId(mapper, SECOND_TRACKING_ID);
- processPosition(mapper, 400, 500);
- processPressure(mapper, RAW_PRESSURE_MAX);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
- WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
-
- // First slot is still ignored, only the second one is active.
- processSlot(mapper, FIRST_SLOT);
- processPosition(mapper, 102, 202);
- processSlot(mapper, SECOND_SLOT);
- processPosition(mapper, 401, 501);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
- WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
-
- // Both slots up, so we get the UP event for the active pointer.
- processSlot(mapper, FIRST_SLOT);
- processId(mapper, INVALID_TRACKING_ID);
- processSlot(mapper, SECOND_SLOT);
- processId(mapper, INVALID_TRACKING_ID);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(
- mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
// --- MultiTouchInputMapperTest_ExternalDevice ---
class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {