Loading include/android/input.h +16 −1 Original line number Diff line number Diff line Loading @@ -771,6 +771,21 @@ enum { * The interpretation of a generic axis is device-specific. */ AMOTION_EVENT_AXIS_GENERIC_16 = 47, /** * Axis constant: X gesture offset axis of a motion event. * * - For a touch pad, reports the distance that a swipe gesture has moved in the X axis, as a * proportion of the touch pad's size. For example, if a touch pad is 1000 units wide, and a * swipe gesture starts at X = 500 then moves to X = 400, this axis would have a value of * -0.1. */ AMOTION_EVENT_AXIS_GESTURE_X_OFFSET = 48, /** * Axis constant: Y gesture offset axis of a motion event. * * The same as {@link AMOTION_EVENT_AXIS_GESTURE_X_OFFSET}, but for the Y axis. */ AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET = 49, /** * Note: This is not an "Axis constant". It does not represent any axis, nor should it be used Loading @@ -778,7 +793,7 @@ enum { * to make some computations (like iterating through all possible axes) cleaner. * Please update the value accordingly if you add a new axis. */ AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE = AMOTION_EVENT_AXIS_GENERIC_16, AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE = AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, // NOTE: If you add a new axis here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list. Loading libs/input/InputEventLabels.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -391,7 +391,9 @@ namespace android { DEFINE_AXIS(GENERIC_13), \ DEFINE_AXIS(GENERIC_14), \ DEFINE_AXIS(GENERIC_15), \ DEFINE_AXIS(GENERIC_16) DEFINE_AXIS(GENERIC_16), \ DEFINE_AXIS(GESTURE_X_OFFSET), \ DEFINE_AXIS(GESTURE_Y_OFFSET) // NOTE: If you add new LEDs here, you must also add them to Input.h #define LEDS_SEQUENCE \ Loading services/inputflinger/InputCommonConverter.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -263,8 +263,11 @@ static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) == common static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) == common::Axis::GENERIC_14); static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) == common::Axis::GENERIC_15); static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) == common::Axis::GENERIC_16); // TODO(hcutts): add GESTURE_X_OFFSET and GESTURE_Y_OFFSET. // If you added a new axis, consider whether this should also be exposed as a HAL axis. Update the // static_assert below and add the new axis here, or leave a comment summarizing your decision. static_assert(static_cast<common::Axis>(AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE) == static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_16)); static_cast<common::Axis>(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET)); static common::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) { common::VideoFrame out; Loading services/inputflinger/reader/mapper/TouchInputMapper.cpp +20 −10 Original line number Diff line number Diff line Loading @@ -3180,7 +3180,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits; // Add delta for all fingers and calculate a common movement delta. float commonDeltaX = 0, commonDeltaY = 0; int32_t commonDeltaRawX = 0, commonDeltaRawY = 0; BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value & mCurrentCookedState.fingerIdBits.value); for (BitSet32 idBits(commonIdBits); !idBits.isEmpty();) { Loading @@ -3193,11 +3193,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi delta.dy += cpd.y - lpd.y; if (first) { commonDeltaX = delta.dx; commonDeltaY = delta.dy; commonDeltaRawX = delta.dx; commonDeltaRawY = delta.dy; } else { commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx); commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy); commonDeltaRawX = calculateCommonVector(commonDeltaRawX, delta.dx); commonDeltaRawY = calculateCommonVector(commonDeltaRawY, delta.dy); } } Loading Loading @@ -3303,7 +3303,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi // Move the reference points based on the overall group motion of the fingers // except in PRESS mode while waiting for a transition to occur. if (mPointerGesture.currentGestureMode != PointerGesture::Mode::PRESS && (commonDeltaX || commonDeltaY)) { (commonDeltaRawX || commonDeltaRawY)) { for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) { uint32_t id = idBits.clearFirstMarkedBit(); PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; Loading @@ -3311,11 +3311,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi delta.dy = 0; } mPointerGesture.referenceTouchX += commonDeltaX; mPointerGesture.referenceTouchY += commonDeltaY; mPointerGesture.referenceTouchX += commonDeltaRawX; mPointerGesture.referenceTouchY += commonDeltaRawY; commonDeltaX *= mPointerXMovementScale; commonDeltaY *= mPointerYMovementScale; float commonDeltaX = commonDeltaRawX * mPointerXMovementScale; float commonDeltaY = commonDeltaRawY * mPointerYMovementScale; rotateDelta(mInputDeviceOrientation, &commonDeltaX, &commonDeltaY); mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); Loading Loading @@ -3346,6 +3346,16 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); if (mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) { float xOffset = static_cast<float>(commonDeltaRawX) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue); float yOffset = static_cast<float>(commonDeltaRawY) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue); mPointerGesture.currentGestureCoords[0] .setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, xOffset); mPointerGesture.currentGestureCoords[0] .setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, yOffset); } } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) { // FREEFORM mode. ALOGD_IF(DEBUG_GESTURES, Loading services/inputflinger/tests/InputReader_test.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -10118,6 +10118,52 @@ TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) { 0, 0, 0, 0, 0)); } TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) { preparePointerMode(25 /*xResolution*/, 25 /*yResolution*/); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); NotifyMotionArgs motionArgs; // Place two fingers down. int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125; processId(mapper, FIRST_TRACKING_ID); processPosition(mapper, x1, y1); processMTSync(mapper); processId(mapper, SECOND_TRACKING_ID); processPosition(mapper, x2, y2); processMTSync(mapper); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(1U, motionArgs.pointerCount); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); ASSERT_EQ(MotionClassification::NONE, motionArgs.classification); ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET)); ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET)); // Move the two fingers down and to the left. int32_t movingDistance = 200; x1 -= movingDistance; y1 += movingDistance; x2 -= movingDistance; y2 += movingDistance; processId(mapper, FIRST_TRACKING_ID); processPosition(mapper, x1, y1); processMTSync(mapper); processId(mapper, SECOND_TRACKING_ID); processPosition(mapper, x2, y2); processMTSync(mapper); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(1U, motionArgs.pointerCount); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification); ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0); ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0); } // --- JoystickInputMapperTest --- class JoystickInputMapperTest : public InputMapperTest { Loading Loading
include/android/input.h +16 −1 Original line number Diff line number Diff line Loading @@ -771,6 +771,21 @@ enum { * The interpretation of a generic axis is device-specific. */ AMOTION_EVENT_AXIS_GENERIC_16 = 47, /** * Axis constant: X gesture offset axis of a motion event. * * - For a touch pad, reports the distance that a swipe gesture has moved in the X axis, as a * proportion of the touch pad's size. For example, if a touch pad is 1000 units wide, and a * swipe gesture starts at X = 500 then moves to X = 400, this axis would have a value of * -0.1. */ AMOTION_EVENT_AXIS_GESTURE_X_OFFSET = 48, /** * Axis constant: Y gesture offset axis of a motion event. * * The same as {@link AMOTION_EVENT_AXIS_GESTURE_X_OFFSET}, but for the Y axis. */ AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET = 49, /** * Note: This is not an "Axis constant". It does not represent any axis, nor should it be used Loading @@ -778,7 +793,7 @@ enum { * to make some computations (like iterating through all possible axes) cleaner. * Please update the value accordingly if you add a new axis. */ AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE = AMOTION_EVENT_AXIS_GENERIC_16, AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE = AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, // NOTE: If you add a new axis here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list. Loading
libs/input/InputEventLabels.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -391,7 +391,9 @@ namespace android { DEFINE_AXIS(GENERIC_13), \ DEFINE_AXIS(GENERIC_14), \ DEFINE_AXIS(GENERIC_15), \ DEFINE_AXIS(GENERIC_16) DEFINE_AXIS(GENERIC_16), \ DEFINE_AXIS(GESTURE_X_OFFSET), \ DEFINE_AXIS(GESTURE_Y_OFFSET) // NOTE: If you add new LEDs here, you must also add them to Input.h #define LEDS_SEQUENCE \ Loading
services/inputflinger/InputCommonConverter.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -263,8 +263,11 @@ static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) == common static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) == common::Axis::GENERIC_14); static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) == common::Axis::GENERIC_15); static_assert(static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) == common::Axis::GENERIC_16); // TODO(hcutts): add GESTURE_X_OFFSET and GESTURE_Y_OFFSET. // If you added a new axis, consider whether this should also be exposed as a HAL axis. Update the // static_assert below and add the new axis here, or leave a comment summarizing your decision. static_assert(static_cast<common::Axis>(AMOTION_EVENT_MAXIMUM_VALID_AXIS_VALUE) == static_cast<common::Axis>(AMOTION_EVENT_AXIS_GENERIC_16)); static_cast<common::Axis>(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET)); static common::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) { common::VideoFrame out; Loading
services/inputflinger/reader/mapper/TouchInputMapper.cpp +20 −10 Original line number Diff line number Diff line Loading @@ -3180,7 +3180,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits; // Add delta for all fingers and calculate a common movement delta. float commonDeltaX = 0, commonDeltaY = 0; int32_t commonDeltaRawX = 0, commonDeltaRawY = 0; BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value & mCurrentCookedState.fingerIdBits.value); for (BitSet32 idBits(commonIdBits); !idBits.isEmpty();) { Loading @@ -3193,11 +3193,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi delta.dy += cpd.y - lpd.y; if (first) { commonDeltaX = delta.dx; commonDeltaY = delta.dy; commonDeltaRawX = delta.dx; commonDeltaRawY = delta.dy; } else { commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx); commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy); commonDeltaRawX = calculateCommonVector(commonDeltaRawX, delta.dx); commonDeltaRawY = calculateCommonVector(commonDeltaRawY, delta.dy); } } Loading Loading @@ -3303,7 +3303,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi // Move the reference points based on the overall group motion of the fingers // except in PRESS mode while waiting for a transition to occur. if (mPointerGesture.currentGestureMode != PointerGesture::Mode::PRESS && (commonDeltaX || commonDeltaY)) { (commonDeltaRawX || commonDeltaRawY)) { for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty();) { uint32_t id = idBits.clearFirstMarkedBit(); PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; Loading @@ -3311,11 +3311,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi delta.dy = 0; } mPointerGesture.referenceTouchX += commonDeltaX; mPointerGesture.referenceTouchY += commonDeltaY; mPointerGesture.referenceTouchX += commonDeltaRawX; mPointerGesture.referenceTouchY += commonDeltaRawY; commonDeltaX *= mPointerXMovementScale; commonDeltaY *= mPointerYMovementScale; float commonDeltaX = commonDeltaRawX * mPointerXMovementScale; float commonDeltaY = commonDeltaRawY * mPointerYMovementScale; rotateDelta(mInputDeviceOrientation, &commonDeltaX, &commonDeltaY); mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY); Loading Loading @@ -3346,6 +3346,16 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY); mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f); if (mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE) { float xOffset = static_cast<float>(commonDeltaRawX) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue); float yOffset = static_cast<float>(commonDeltaRawY) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue); mPointerGesture.currentGestureCoords[0] .setAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET, xOffset); mPointerGesture.currentGestureCoords[0] .setAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET, yOffset); } } else if (mPointerGesture.currentGestureMode == PointerGesture::Mode::FREEFORM) { // FREEFORM mode. ALOGD_IF(DEBUG_GESTURES, Loading
services/inputflinger/tests/InputReader_test.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -10118,6 +10118,52 @@ TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) { 0, 0, 0, 0, 0)); } TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) { preparePointerMode(25 /*xResolution*/, 25 /*yResolution*/); MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); NotifyMotionArgs motionArgs; // Place two fingers down. int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125; processId(mapper, FIRST_TRACKING_ID); processPosition(mapper, x1, y1); processMTSync(mapper); processId(mapper, SECOND_TRACKING_ID); processPosition(mapper, x2, y2); processMTSync(mapper); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(1U, motionArgs.pointerCount); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); ASSERT_EQ(MotionClassification::NONE, motionArgs.classification); ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET)); ASSERT_EQ(0, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET)); // Move the two fingers down and to the left. int32_t movingDistance = 200; x1 -= movingDistance; y1 += movingDistance; x2 -= movingDistance; y2 += movingDistance; processId(mapper, FIRST_TRACKING_ID); processPosition(mapper, x1, y1); processMTSync(mapper); processId(mapper, SECOND_TRACKING_ID); processPosition(mapper, x2, y2); processMTSync(mapper); processSync(mapper); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(1U, motionArgs.pointerCount); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action); ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification); ASSERT_LT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET), 0); ASSERT_GT(motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET), 0); } // --- JoystickInputMapperTest --- class JoystickInputMapperTest : public InputMapperTest { Loading