diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-09-01 23:21:23 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-09-01 23:21:23 +0000 |
commit | 47224b75201d405d2bdca216d906565b3272c94c (patch) | |
tree | a8e59a999828c61599f54a860e4244b63be01301 | |
parent | b662e5da18a583571059c2ea51d80ebfa32650b6 (diff) | |
parent | 7fa3483dfb0b6eefdb8eeb990172d673bbed2665 (diff) | |
download | native-47224b75201d405d2bdca216d906565b3272c94c.tar.gz |
Snap for 9018797 from 7fa3483dfb0b6eefdb8eeb990172d673bbed2665 to tm-qpr1-release
Change-Id: I65871b1a5ac8cef1e7d9113e718b9a1768c9ec3f
-rw-r--r-- | services/inputflinger/reader/mapper/TouchInputMapper.cpp | 46 | ||||
-rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 113 |
2 files changed, 127 insertions, 32 deletions
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 637b1cb263..428fe10156 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -44,6 +44,8 @@ static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10); // --- Static Definitions --- +static const DisplayViewport kUninitializedViewport; + template <typename T> inline static void swap(T& a, T& b) { T temp = a; @@ -390,6 +392,10 @@ void TouchInputMapper::configure(nsecs_t when, const InputReaderConfiguration* c } if (changes && resetNeeded) { + // If the device needs to be reset, cancel any ongoing gestures and reset the state. + cancelTouch(when, when); + reset(when); + // Send reset, unless this is the first time the device has been configured, // in which case the reader will call reset itself after all mappers are ready. NotifyDeviceResetArgs args(getContext()->getNextId(), when, getDeviceId()); @@ -877,7 +883,7 @@ void TouchInputMapper::initializeOrientedRanges() { } void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) { - DeviceMode oldDeviceMode = mDeviceMode; + const DeviceMode oldDeviceMode = mDeviceMode; resolveExternalStylusPresence(); @@ -906,42 +912,37 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) mDeviceMode = DeviceMode::UNSCALED; } - // Ensure we have valid X and Y axes. + const std::optional<DisplayViewport> newViewportOpt = findViewport(); + + // Ensure the device is valid and can be used. if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) { ALOGW("Touch device '%s' did not report support for X or Y axis! " "The device will be inoperable.", getDeviceName().c_str()); mDeviceMode = DeviceMode::DISABLED; - return; - } - - // Get associated display dimensions. - std::optional<DisplayViewport> newViewport = findViewport(); - if (!newViewport) { + } else if (!newViewportOpt) { ALOGI("Touch device '%s' could not query the properties of its associated " "display. The device will be inoperable until the display size " "becomes available.", getDeviceName().c_str()); mDeviceMode = DeviceMode::DISABLED; - return; - } - - if (!newViewport->isActive) { + } else if (!newViewportOpt->isActive) { ALOGI("Disabling %s (device %i) because the associated viewport is not active", getDeviceName().c_str(), getDeviceId()); mDeviceMode = DeviceMode::DISABLED; - return; } // Raw width and height in the natural orientation. const int32_t rawWidth = mRawPointerAxes.getRawWidth(); const int32_t rawHeight = mRawPointerAxes.getRawHeight(); - const bool viewportChanged = mViewport != *newViewport; + const DisplayViewport& newViewport = newViewportOpt.value_or(kUninitializedViewport); + const bool viewportChanged = mViewport != newViewport; bool skipViewportUpdate = false; if (viewportChanged) { - const bool viewportOrientationChanged = mViewport.orientation != newViewport->orientation; - mViewport = *newViewport; + const bool viewportOrientationChanged = mViewport.orientation != newViewport.orientation; + const bool viewportDisplayIdChanged = mViewport.displayId != newViewport.displayId; + mViewport = newViewport; if (mDeviceMode == DeviceMode::DIRECT || mDeviceMode == DeviceMode::POINTER) { // Convert rotated viewport to the natural orientation. @@ -1016,8 +1017,9 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) : getInverseRotation(mViewport.orientation); // For orientation-aware devices that work in the un-rotated coordinate space, the // viewport update should be skipped if it is only a change in the orientation. - skipViewportUpdate = mParameters.orientationAware && mDisplayWidth == oldDisplayWidth && - mDisplayHeight == oldDisplayHeight && viewportOrientationChanged; + skipViewportUpdate = !viewportDisplayIdChanged && mParameters.orientationAware && + mDisplayWidth == oldDisplayWidth && mDisplayHeight == oldDisplayHeight && + viewportOrientationChanged; // Apply the input device orientation for the device. mInputDeviceOrientation = @@ -1094,10 +1096,6 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) // of the diagonal axis of the touch pad. Touches that are wider than this are // translated into freeform gestures. mPointerGestureMaxSwipeWidth = mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal; - - // Abort current pointer usages because the state has changed. - const nsecs_t readTime = when; // synthetic event - abortPointerUsage(when, readTime, 0 /*policyFlags*/); } // Inform the dispatcher about the changes. @@ -1926,6 +1924,10 @@ void TouchInputMapper::dispatchVirtualKey(nsecs_t when, nsecs_t readTime, uint32 } void TouchInputMapper::abortTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) { + if (mCurrentMotionAborted) { + // Current motion event was already aborted. + return; + } BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits; if (!currentIdBits.isEmpty()) { int32_t metaState = getContext()->getGlobalMetaState(); diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index c36704bf15..75b8dd1953 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -2938,6 +2938,8 @@ protected: mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy, *mFakeListener); mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes); + // Consume the device reset notification generated when adding a new device. + mFakeListener->assertNotifyDeviceResetWasCalled(); } void SetUp() override { @@ -2962,6 +2964,8 @@ protected: mReader->loopOnce(); } mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes); + // Loop the reader to flush the input listener queue. + mReader->loopOnce(); } std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name, @@ -2985,6 +2989,8 @@ protected: configureDevice(0); mDevice->reset(ARBITRARY_TIME); mapper.reset(ARBITRARY_TIME); + // Loop the reader to flush the input listener queue. + mReader->loopOnce(); return mapper; } @@ -3010,6 +3016,7 @@ protected: event.code = code; event.value = value; mapper.process(&event); + // Loop the reader to flush the input listener queue. mReader->loopOnce(); } @@ -4907,7 +4914,6 @@ TEST_F(CursorInputMapperTest, Process_PointerCapture) { ASSERT_TRUE(mReader->getContext()->getGeneration() != generation); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs)); - ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime); ASSERT_EQ(DEVICE_ID, resetArgs.deviceId); process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10); @@ -6690,6 +6696,89 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsV toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0)); } +TEST_F(SingleTouchInputMapperTest, + Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) { + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); + prepareAxes(POSITION); + SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>(); + NotifyMotionArgs motionArgs; + + // Down. + processDown(mapper, 100, 200); + processSync(mapper); + + // We should receive a down event + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + + // Change display id + clearViewports(); + prepareSecondaryDisplay(ViewportType::INTERNAL); + + // We should receive a cancel event + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action); + // Then receive reset called + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled()); +} + +TEST_F(SingleTouchInputMapperTest, + Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) { + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareButtons(); + prepareAxes(POSITION); + SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>(); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled()); + NotifyMotionArgs motionArgs; + + // Start a new gesture. + processDown(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + + // Make the viewport inactive. This will put the device in disabled mode. + auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL); + viewport->isActive = false; + mFakePolicy->updateViewport(*viewport); + configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + + // We should receive a cancel event for the ongoing gesture. + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action); + // Then we should be notified that the device was reset. + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled()); + + // No events are generated while the viewport is inactive. + processMove(mapper, 101, 201); + processSync(mapper); + processDown(mapper, 102, 202); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); + + // Make the viewport active again. The device should resume processing events. + viewport->isActive = true; + mFakePolicy->updateViewport(*viewport); + configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); + + // The device is reset because it changes back to direct mode, without generating any events. + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); + + // Start a new gesture. + processDown(mapper, 100, 200); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); + + // No more events. + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasNotCalled()); +} + // --- TouchDisplayProjectionTest --- class TouchDisplayProjectionTest : public SingleTouchInputMapperTest { @@ -8547,27 +8636,27 @@ TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) { ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport)); configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); - // Finger move + // The ongoing touch should be canceled immediately + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action); + + // Finger move is ignored x += 10, y += 10; processPosition(mapper, x, y); processSync(mapper); - - ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); - EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); // Reactivate display viewport displayViewport.isActive = true; ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport)); configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); - // Finger move again + // Finger move again starts new gesture x += 10, y += 10; processPosition(mapper, x, y); processSync(mapper); - - // Gesture is aborted, so events after display is activated won't be dispatched until there is - // no pointer on the touch device. - mFakeListener->assertNotifyMotionWasNotCalled(); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); + EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); } TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) { @@ -8725,6 +8814,10 @@ TEST_F(MultiTouchInputMapperTest, VideoFrames_WhenNotOrientationAware_AreRotated // window's coordinate space. frames[0].rotate(getInverseRotation(orientation)); ASSERT_EQ(frames, motionArgs.videoFrames); + + // Release finger. + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); } } |