Loading services/inputflinger/reader/mapper/TouchInputMapper.cpp +32 −13 Original line number Original line Diff line number Diff line Loading @@ -608,8 +608,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { if (hasStylus()) { if (hasStylus()) { mSource |= AINPUT_SOURCE_STYLUS; mSource |= AINPUT_SOURCE_STYLUS; } } } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN && } else if (isTouchScreen()) { mParameters.hasAssociatedDisplay) { mSource = AINPUT_SOURCE_TOUCHSCREEN; mSource = AINPUT_SOURCE_TOUCHSCREEN; mDeviceMode = DeviceMode::DIRECT; mDeviceMode = DeviceMode::DIRECT; if (hasStylus()) { if (hasStylus()) { Loading Loading @@ -1453,8 +1452,11 @@ void TouchInputMapper::sync(nsecs_t when) { void TouchInputMapper::processRawTouches(bool timeout) { void TouchInputMapper::processRawTouches(bool timeout) { if (mDeviceMode == DeviceMode::DISABLED) { if (mDeviceMode == DeviceMode::DISABLED) { // Drop all input if the device is disabled. // Drop all input if the device is disabled. cancelTouch(mCurrentRawState.when); mCurrentRawState.clear(); mCurrentRawState.clear(); mRawStatesPending.clear(); mRawStatesPending.clear(); mCurrentCookedState.clear(); updateTouchSpots(); return; return; } } Loading Loading @@ -1586,17 +1588,7 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { dispatchPointerUsage(when, policyFlags, pointerUsage); dispatchPointerUsage(when, policyFlags, pointerUsage); } else { } else { if (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches && updateTouchSpots(); 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); } if (!mCurrentMotionAborted) { if (!mCurrentMotionAborted) { dispatchButtonRelease(when, policyFlags); dispatchButtonRelease(when, policyFlags); Loading Loading @@ -1625,6 +1617,33 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { mLastCookedState.copyFrom(mCurrentCookedState); 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) { void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) { if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus() && mExternalStylusId != -1) { if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus() && mExternalStylusId != -1) { mCurrentRawState.buttonState |= mExternalStylusState.buttons; mCurrentRawState.buttonState |= mExternalStylusState.buttons; Loading services/inputflinger/reader/mapper/TouchInputMapper.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -757,6 +757,12 @@ private: PointerCoords* outCoords, const uint32_t* outIdToIndex, PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const; 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); bool isPointInsideSurface(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); Loading services/inputflinger/tests/InputReader_test.cpp +51 −0 Original line number Original line Diff line number Diff line Loading @@ -7362,6 +7362,57 @@ TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) { mFakeListener->assertNotifyMotionWasNotCalled(); 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) { TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) { // Setup the first touch screen device. // Setup the first touch screen device. prepareAxes(POSITION | ID | SLOT); prepareAxes(POSITION | ID | SLOT); Loading Loading
services/inputflinger/reader/mapper/TouchInputMapper.cpp +32 −13 Original line number Original line Diff line number Diff line Loading @@ -608,8 +608,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { if (hasStylus()) { if (hasStylus()) { mSource |= AINPUT_SOURCE_STYLUS; mSource |= AINPUT_SOURCE_STYLUS; } } } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN && } else if (isTouchScreen()) { mParameters.hasAssociatedDisplay) { mSource = AINPUT_SOURCE_TOUCHSCREEN; mSource = AINPUT_SOURCE_TOUCHSCREEN; mDeviceMode = DeviceMode::DIRECT; mDeviceMode = DeviceMode::DIRECT; if (hasStylus()) { if (hasStylus()) { Loading Loading @@ -1453,8 +1452,11 @@ void TouchInputMapper::sync(nsecs_t when) { void TouchInputMapper::processRawTouches(bool timeout) { void TouchInputMapper::processRawTouches(bool timeout) { if (mDeviceMode == DeviceMode::DISABLED) { if (mDeviceMode == DeviceMode::DISABLED) { // Drop all input if the device is disabled. // Drop all input if the device is disabled. cancelTouch(mCurrentRawState.when); mCurrentRawState.clear(); mCurrentRawState.clear(); mRawStatesPending.clear(); mRawStatesPending.clear(); mCurrentCookedState.clear(); updateTouchSpots(); return; return; } } Loading Loading @@ -1586,17 +1588,7 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { dispatchPointerUsage(when, policyFlags, pointerUsage); dispatchPointerUsage(when, policyFlags, pointerUsage); } else { } else { if (mDeviceMode == DeviceMode::DIRECT && mConfig.showTouches && updateTouchSpots(); 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); } if (!mCurrentMotionAborted) { if (!mCurrentMotionAborted) { dispatchButtonRelease(when, policyFlags); dispatchButtonRelease(when, policyFlags); Loading Loading @@ -1625,6 +1617,33 @@ void TouchInputMapper::cookAndDispatch(nsecs_t when) { mLastCookedState.copyFrom(mCurrentCookedState); 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) { void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) { if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus() && mExternalStylusId != -1) { if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus() && mExternalStylusId != -1) { mCurrentRawState.buttonState |= mExternalStylusState.buttons; mCurrentRawState.buttonState |= mExternalStylusState.buttons; Loading
services/inputflinger/reader/mapper/TouchInputMapper.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -757,6 +757,12 @@ private: PointerCoords* outCoords, const uint32_t* outIdToIndex, PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const; 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); bool isPointInsideSurface(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y); Loading
services/inputflinger/tests/InputReader_test.cpp +51 −0 Original line number Original line Diff line number Diff line Loading @@ -7362,6 +7362,57 @@ TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) { mFakeListener->assertNotifyMotionWasNotCalled(); 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) { TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShowTouches) { // Setup the first touch screen device. // Setup the first touch screen device. prepareAxes(POSITION | ID | SLOT); prepareAxes(POSITION | ID | SLOT); Loading