Clear cooked state and touch spots when disabled
Bug: 177403144
Test: Touch spots are gone after pressing power button with a finger on
the display.
Change-Id: I8c7991d728ba3ff84f982185ac6a30d1e2cae33e
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index fb30b88..b748bfe 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -608,8 +608,7 @@
if (hasStylus()) {
mSource |= AINPUT_SOURCE_STYLUS;
}
- } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN &&
- mParameters.hasAssociatedDisplay) {
+ } else if (isTouchScreen()) {
mSource = AINPUT_SOURCE_TOUCHSCREEN;
mDeviceMode = DeviceMode::DIRECT;
if (hasStylus()) {
@@ -1453,8 +1452,11 @@
void TouchInputMapper::processRawTouches(bool timeout) {
if (mDeviceMode == DeviceMode::DISABLED) {
// Drop all input if the device is disabled.
+ cancelTouch(mCurrentRawState.when);
mCurrentRawState.clear();
mRawStatesPending.clear();
+ mCurrentCookedState.clear();
+ updateTouchSpots();
return;
}
@@ -1586,17 +1588,7 @@
dispatchPointerUsage(when, policyFlags, pointerUsage);
} else {
- if (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches &&
- mPointerController != nullptr) {
- mPointerController->setPresentation(PointerControllerInterface::Presentation::SPOT);
- mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
-
- mPointerController->setButtonState(mCurrentRawState.buttonState);
- mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex,
- mCurrentCookedState.cookedPointerData.touchingIdBits,
- mViewport.displayId);
- }
+ updateTouchSpots();
if (!mCurrentMotionAborted) {
dispatchButtonRelease(when, policyFlags);
@@ -1625,6 +1617,33 @@
mLastCookedState.copyFrom(mCurrentCookedState);
}
+void TouchInputMapper::updateTouchSpots() {
+ if (!mConfig.showTouches || mPointerController == nullptr) {
+ return;
+ }
+
+ // Update touch spots when this is a touchscreen even when it's not enabled so that we can
+ // clear touch spots.
+ if (mDeviceMode != DeviceMode::DIRECT &&
+ (mDeviceMode != DeviceMode::DISABLED || !isTouchScreen())) {
+ return;
+ }
+
+ mPointerController->setPresentation(PointerControllerInterface::Presentation::SPOT);
+ mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
+
+ mPointerController->setButtonState(mCurrentRawState.buttonState);
+ mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ mCurrentCookedState.cookedPointerData.touchingIdBits,
+ mViewport.displayId);
+}
+
+bool TouchInputMapper::isTouchScreen() {
+ return mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN &&
+ mParameters.hasAssociatedDisplay;
+}
+
void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
mCurrentRawState.buttonState |= mExternalStylusState.buttons;
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index df6581d..6621825 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -757,6 +757,12 @@
PointerCoords* outCoords, const uint32_t* outIdToIndex,
BitSet32 idBits) const;
+ // Returns if this touch device is a touch screen with an associated display.
+ bool isTouchScreen();
+ // Updates touch spots if they are enabled. Should only be used when this device is a
+ // touchscreen.
+ void updateTouchSpots();
+
bool isPointInsideSurface(int32_t x, int32_t y);
const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 91d5864..36da8dd 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -7362,6 +7362,57 @@
mFakeListener->assertNotifyMotionWasNotCalled();
}
+TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ DISPLAY_ORIENTATION_0, true /*isActive*/, UNIQUE_ID, NO_PORT,
+ ViewportType::INTERNAL);
+ std::optional<DisplayViewport> optionalDisplayViewport =
+ mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
+ ASSERT_TRUE(optionalDisplayViewport.has_value());
+ DisplayViewport displayViewport = *optionalDisplayViewport;
+
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ prepareAxes(POSITION);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // Finger down
+ int32_t x = 100, y = 100;
+ processPosition(mapper, x, y);
+ processSync(mapper);
+
+ NotifyMotionArgs motionArgs;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+
+ // Deactivate display viewport
+ displayViewport.isActive = false;
+ ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+ // Finger move
+ 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);
+
+ // Reactivate display viewport
+ displayViewport.isActive = true;
+ ASSERT_TRUE(mFakePolicy->updateViewport(displayViewport));
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+ // Finger move again
+ 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();
+}
+
TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) {
// Setup the first touch screen device.
prepareAxes(POSITION | ID | SLOT);