diff options
author | Arpit Singh <arpitks@google.com> | 2023-12-20 14:41:10 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-12-20 18:37:14 +0000 |
commit | c0749b449bb91f4a7d3356a9553aa5f71c0db24a (patch) | |
tree | ff24e7e2d0fe1410b06341972e054f4381a1436e | |
parent | 8a40509f77e0a410e9f30a60e68a481862f0bfcb (diff) | |
download | native-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
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 { |