Loading include/input/Input.h +22 −6 Original line number Diff line number Diff line Loading @@ -99,6 +99,18 @@ enum { /* Motion event is inconsistent with previously sent motion events. */ AMOTION_EVENT_FLAG_TAINTED = android::os::IInputConstants::INPUT_EVENT_FLAG_TAINTED, /** Private flag, not used in Java. */ AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION = android::os::IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION, /** Private flag, not used in Java. */ AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = android::os::IInputConstants:: MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION, /** Mask for all private flags that are not used in Java. */ AMOTION_EVENT_PRIVATE_FLAG_MASK = AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION, }; /** Loading Loading @@ -209,8 +221,12 @@ vec2 transformWithoutTranslation(const ui::Transform& transform, const vec2& xy) * Transform an angle on the x-y plane. An angle of 0 radians corresponds to "north" or * pointing upwards in the negative Y direction, a positive angle points towards the right, and a * negative angle points towards the left. * * If the angle represents a direction that needs to be preserved, set isDirectional to true to get * an output range of [-pi, pi]. If the angle's direction does not need to be preserved, set * isDirectional to false to get an output range of [-pi/2, pi/2]. */ float transformAngle(const ui::Transform& transform, float angleRadians); float transformAngle(const ui::Transform& transform, float angleRadians, bool isDirectional); /** * The type of the InputEvent. Loading Loading @@ -472,7 +488,7 @@ struct PointerCoords { // axes, however the window scaling will not. void scale(float globalScale, float windowXScale, float windowYScale); void transform(const ui::Transform& transform); void transform(const ui::Transform& transform, int32_t motionEventFlags); inline float getX() const { return getAxisValue(AMOTION_EVENT_AXIS_X); Loading Loading @@ -940,10 +956,10 @@ public: // relative mouse device (since SOURCE_RELATIVE_MOUSE is a non-pointer source). These methods // are used to apply these transformations for different axes. static vec2 calculateTransformedXY(uint32_t source, const ui::Transform&, const vec2& xy); static float calculateTransformedAxisValue(int32_t axis, uint32_t source, const ui::Transform&, const PointerCoords&); static PointerCoords calculateTransformedCoords(uint32_t source, const ui::Transform&, const PointerCoords&); static float calculateTransformedAxisValue(int32_t axis, uint32_t source, int32_t flags, const ui::Transform&, const PointerCoords&); static PointerCoords calculateTransformedCoords(uint32_t source, int32_t flags, const ui::Transform&, const PointerCoords&); // The rounding precision for transformed motion events. static constexpr float ROUNDING_PRECISION = 0.001f; Loading libs/input/Input.cpp +30 −13 Original line number Diff line number Diff line Loading @@ -96,6 +96,19 @@ int32_t resolveActionForSplitMotionEvent( return AMOTION_EVENT_ACTION_DOWN; } float transformOrientation(const ui::Transform& transform, const PointerCoords& coords, int32_t motionEventFlags) { if ((motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION) == 0) { return 0; } const bool isDirectionalAngle = (motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION) != 0; return transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), isDirectionalAngle); } } // namespace const char* motionClassificationToString(MotionClassification classification) { Loading Loading @@ -187,7 +200,7 @@ vec2 transformWithoutTranslation(const ui::Transform& transform, const vec2& xy) return roundTransformedCoords(transformedXy - transformedOrigin); } float transformAngle(const ui::Transform& transform, float angleRadians) { float transformAngle(const ui::Transform& transform, float angleRadians, bool isDirectional) { // Construct and transform a vector oriented at the specified clockwise angle from vertical. // Coordinate system: down is increasing Y, right is increasing X. float x = sinf(angleRadians); Loading @@ -201,6 +214,11 @@ float transformAngle(const ui::Transform& transform, float angleRadians) { transformedPoint.x -= origin.x; transformedPoint.y -= origin.y; if (!isDirectional && transformedPoint.y > 0) { // Limit the range of atan2f to [-pi/2, pi/2] by reversing the direction of the vector. transformedPoint *= -1; } // Derive the transformed vector's clockwise angle from vertical. // The return value of atan2f is in range [-pi, pi] which conforms to the orientation API. return atan2f(transformedPoint.x, -transformedPoint.y); Loading Loading @@ -530,7 +548,7 @@ bool PointerCoords::operator==(const PointerCoords& other) const { return true; } void PointerCoords::transform(const ui::Transform& transform) { void PointerCoords::transform(const ui::Transform& transform, int32_t motionEventFlags) { const vec2 xy = transform.transform(getXYValue()); setAxisValue(AMOTION_EVENT_AXIS_X, xy.x); setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y); Loading @@ -544,9 +562,9 @@ void PointerCoords::transform(const ui::Transform& transform) { setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); } if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_ORIENTATION)) { const float val = getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(transform, val)); if ((motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION) != 0) { setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformOrientation(transform, *this, motionEventFlags)); } } Loading Loading @@ -723,13 +741,13 @@ const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { const PointerCoords& coords = *getHistoricalRawPointerCoords(pointerIndex, historicalIndex); return calculateTransformedAxisValue(axis, mSource, mRawTransform, coords); return calculateTransformedAxisValue(axis, mSource, mFlags, mRawTransform, coords); } float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { const PointerCoords& coords = *getHistoricalRawPointerCoords(pointerIndex, historicalIndex); return calculateTransformedAxisValue(axis, mSource, mTransform, coords); return calculateTransformedAxisValue(axis, mSource, mFlags, mTransform, coords); } ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { Loading Loading @@ -787,7 +805,7 @@ void MotionEvent::applyTransform(const std::array<float, 9>& matrix) { // Apply the transformation to all samples. std::for_each(mSamplePointerCoords.begin(), mSamplePointerCoords.end(), [&transform](PointerCoords& c) { c.transform(transform); }); [&](PointerCoords& c) { c.transform(transform, mFlags); }); if (mRawXCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION && mRawYCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) { Loading Loading @@ -1059,7 +1077,7 @@ vec2 MotionEvent::calculateTransformedXY(uint32_t source, const ui::Transform& t } // Keep in sync with calculateTransformedCoords. float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, int32_t flags, const ui::Transform& transform, const PointerCoords& coords) { if (shouldDisregardTransformation(source)) { Loading @@ -1081,7 +1099,7 @@ float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, } if (axis == AMOTION_EVENT_AXIS_ORIENTATION) { return transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); return transformOrientation(transform, coords, flags); } return coords.getAxisValue(axis); Loading @@ -1089,7 +1107,7 @@ float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, // Keep in sync with calculateTransformedAxisValue. This is an optimization of // calculateTransformedAxisValue for all PointerCoords axes. PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, int32_t flags, const ui::Transform& transform, const PointerCoords& coords) { if (shouldDisregardTransformation(source)) { Loading @@ -1109,8 +1127,7 @@ PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION))); transformOrientation(transform, coords, flags)); return out; } Loading libs/input/android/os/IInputConstants.aidl +25 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,31 @@ interface IInputConstants */ const int MOTION_EVENT_FLAG_NO_FOCUS_CHANGE = 0x40; /** * This flag indicates that the event has a valid value for AXIS_ORIENTATION. * * This is a private flag that is not used in Java. * @hide */ const int MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION = 0x80; /** * This flag indicates that the pointers' AXIS_ORIENTATION can be used to precisely determine * the direction in which the tool is pointing. The value of the orientation axis will be in * the range [-pi, pi], which represents a full circle. This is usually supported by devices * like styluses. * * Conversely, AXIS_ORIENTATION cannot be used to tell which direction the tool is pointing * when this flag is not set. In this case, the axis value will have a range of [-pi/2, pi/2], * which represents half a circle. This is usually the case for devices like touchscreens and * touchpads, for which it is difficult to tell which direction along the major axis of the * touch ellipse the finger is pointing. * * This is a private flag that is not used in Java. * @hide */ const int MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = 0x100; /** * The input event was generated or modified by accessibility service. * Shared by both KeyEvent and MotionEvent flags, so this value should not overlap with either Loading libs/input/tests/InputEvent_test.cpp +125 −14 Original line number Diff line number Diff line Loading @@ -26,23 +26,39 @@ namespace android { namespace { // Default display id. static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT; constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT; static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION; constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION; static constexpr auto POINTER_0_DOWN = constexpr auto POINTER_0_DOWN = AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); static constexpr auto POINTER_1_DOWN = constexpr auto POINTER_1_DOWN = AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); static constexpr auto POINTER_0_UP = constexpr auto POINTER_0_UP = AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); static constexpr auto POINTER_1_UP = constexpr auto POINTER_1_UP = AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); std::array<float, 9> asFloat9(const ui::Transform& t) { std::array<float, 9> mat{}; mat[0] = t[0][0]; mat[1] = t[1][0]; mat[2] = t[2][0]; mat[3] = t[0][1]; mat[4] = t[1][1]; mat[5] = t[2][1]; mat[6] = t[0][2]; mat[7] = t[1][2]; mat[8] = t[2][2]; return mat; } class BaseTest : public testing::Test { protected: static constexpr std::array<uint8_t, 32> HMAC = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, Loading @@ -50,6 +66,8 @@ protected: 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; }; } // namespace // --- PointerCoordsTest --- class PointerCoordsTest : public BaseTest { Loading Loading @@ -344,13 +362,15 @@ void MotionEventTest::SetUp() { } void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION; event->initialize(mId, 2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, HMAC, AMOTION_EVENT_ACTION_MOVE, 0, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE, mTransform, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, mRawTransform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, mPointerProperties, mSamples[0].pointerCoords); AMOTION_EVENT_ACTION_MOVE, 0, flags, AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE, mTransform, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, mRawTransform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, mPointerProperties, mSamples[0].pointerCoords); event->addSample(ARBITRARY_EVENT_TIME + 1, mSamples[1].pointerCoords); event->addSample(ARBITRARY_EVENT_TIME + 2, mSamples[2].pointerCoords); } Loading @@ -364,7 +384,10 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { ASSERT_EQ(DISPLAY_ID, event->getDisplayId()); EXPECT_EQ(HMAC, event->getHmac()); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction()); ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags()); ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION, event->getFlags()); ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags()); ASSERT_EQ(AMETA_ALT_ON, event->getMetaState()); ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState()); Loading Loading @@ -799,8 +822,10 @@ TEST_F(MotionEventTest, Transform) { } MotionEvent event; ui::Transform identityTransform; const int32_t flags = AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION; event.initialize(InputEvent::nextId(), /*deviceId=*/0, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, /*actionButton=*/0, /*flags=*/0, INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, /*actionButton=*/0, flags, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE, identityTransform, /*xPrecision=*/0, /*yPrecision=*/0, /*xCursorPosition=*/3 + RADIUS, /*yCursorPosition=*/2, Loading Loading @@ -1087,4 +1112,90 @@ TEST_F(MotionEventTest, CoordinatesAreRoundedAppropriately) { ASSERT_EQ(EXPECTED.y, event.getYCursorPosition()); } TEST_F(MotionEventTest, InvalidOrientationNotRotated) { // This touch event does not have a value for AXIS_ORIENTATION, and the flags are implicitly // set to 0. The transform is set to a 90-degree rotation. MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) .downTime(ARBITRARY_DOWN_TIME) .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4)) .transform(ui::Transform(ui::Transform::ROT_90, 100, 100)) .rawTransform(ui::Transform(ui::Transform::FLIP_H, 50, 50)) .build(); ASSERT_EQ(event.getOrientation(/*pointerIndex=*/0), 0.f); event.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); ASSERT_EQ(event.getOrientation(/*pointerIndex=*/0), 0.f); event.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); ASSERT_EQ(event.getOrientation(/*pointerIndex=*/0), 0.f); event.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); ASSERT_EQ(event.getOrientation(/*pointerIndex=*/0), 0.f); } TEST_F(MotionEventTest, ValidZeroOrientationRotated) { // This touch events will implicitly have a value of 0 for its AXIS_ORIENTATION. auto builder = MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) .downTime(ARBITRARY_DOWN_TIME) .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4)) .transform(ui::Transform(ui::Transform::ROT_90, 100, 100)) .rawTransform(ui::Transform(ui::Transform::FLIP_H, 50, 50)) .addFlag(AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION); MotionEvent nonDirectionalEvent = builder.build(); MotionEvent directionalEvent = builder.addFlag(AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION).build(); // The angle is rotated by the initial transform, a 90-degree rotation. ASSERT_NEAR(fabs(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0)), M_PI_2, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), M_PI_2, EPSILON); nonDirectionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); directionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), 0.f, EPSILON); ASSERT_NEAR(fabs(directionalEvent.getOrientation(/*pointerIndex=*/0)), M_PI, EPSILON); nonDirectionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); directionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), 0.f, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), 0.f, EPSILON); nonDirectionalEvent.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); directionalEvent.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); ASSERT_NEAR(fabs(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0)), M_PI_2, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), -M_PI_2, EPSILON); } TEST_F(MotionEventTest, ValidNonZeroOrientationRotated) { const float initial = 1.f; auto builder = MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) .downTime(ARBITRARY_DOWN_TIME) .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER) .x(4) .y(4) .axis(AMOTION_EVENT_AXIS_ORIENTATION, initial)) .transform(ui::Transform(ui::Transform::ROT_90, 100, 100)) .rawTransform(ui::Transform(ui::Transform::FLIP_H, 50, 50)) .addFlag(AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION); MotionEvent nonDirectionalEvent = builder.build(); MotionEvent directionalEvent = builder.addFlag(AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION).build(); // The angle is rotated by the initial transform, a 90-degree rotation. ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), initial - M_PI_2, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), initial + M_PI_2, EPSILON); nonDirectionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); directionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), initial, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), initial - M_PI, EPSILON); nonDirectionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); directionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), initial, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), initial, EPSILON); nonDirectionalEvent.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); directionalEvent.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), initial - M_PI_2, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), initial - M_PI_2, EPSILON); } } // namespace android libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,9 @@ PublishMotionArgs::PublishMotionArgs(int32_t inAction, nsecs_t inDownTime, hmac = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION; if (action == AMOTION_EVENT_ACTION_CANCEL) { flags |= AMOTION_EVENT_FLAG_CANCELED; } Loading Loading
include/input/Input.h +22 −6 Original line number Diff line number Diff line Loading @@ -99,6 +99,18 @@ enum { /* Motion event is inconsistent with previously sent motion events. */ AMOTION_EVENT_FLAG_TAINTED = android::os::IInputConstants::INPUT_EVENT_FLAG_TAINTED, /** Private flag, not used in Java. */ AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION = android::os::IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION, /** Private flag, not used in Java. */ AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = android::os::IInputConstants:: MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION, /** Mask for all private flags that are not used in Java. */ AMOTION_EVENT_PRIVATE_FLAG_MASK = AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION, }; /** Loading Loading @@ -209,8 +221,12 @@ vec2 transformWithoutTranslation(const ui::Transform& transform, const vec2& xy) * Transform an angle on the x-y plane. An angle of 0 radians corresponds to "north" or * pointing upwards in the negative Y direction, a positive angle points towards the right, and a * negative angle points towards the left. * * If the angle represents a direction that needs to be preserved, set isDirectional to true to get * an output range of [-pi, pi]. If the angle's direction does not need to be preserved, set * isDirectional to false to get an output range of [-pi/2, pi/2]. */ float transformAngle(const ui::Transform& transform, float angleRadians); float transformAngle(const ui::Transform& transform, float angleRadians, bool isDirectional); /** * The type of the InputEvent. Loading Loading @@ -472,7 +488,7 @@ struct PointerCoords { // axes, however the window scaling will not. void scale(float globalScale, float windowXScale, float windowYScale); void transform(const ui::Transform& transform); void transform(const ui::Transform& transform, int32_t motionEventFlags); inline float getX() const { return getAxisValue(AMOTION_EVENT_AXIS_X); Loading Loading @@ -940,10 +956,10 @@ public: // relative mouse device (since SOURCE_RELATIVE_MOUSE is a non-pointer source). These methods // are used to apply these transformations for different axes. static vec2 calculateTransformedXY(uint32_t source, const ui::Transform&, const vec2& xy); static float calculateTransformedAxisValue(int32_t axis, uint32_t source, const ui::Transform&, const PointerCoords&); static PointerCoords calculateTransformedCoords(uint32_t source, const ui::Transform&, const PointerCoords&); static float calculateTransformedAxisValue(int32_t axis, uint32_t source, int32_t flags, const ui::Transform&, const PointerCoords&); static PointerCoords calculateTransformedCoords(uint32_t source, int32_t flags, const ui::Transform&, const PointerCoords&); // The rounding precision for transformed motion events. static constexpr float ROUNDING_PRECISION = 0.001f; Loading
libs/input/Input.cpp +30 −13 Original line number Diff line number Diff line Loading @@ -96,6 +96,19 @@ int32_t resolveActionForSplitMotionEvent( return AMOTION_EVENT_ACTION_DOWN; } float transformOrientation(const ui::Transform& transform, const PointerCoords& coords, int32_t motionEventFlags) { if ((motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION) == 0) { return 0; } const bool isDirectionalAngle = (motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION) != 0; return transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), isDirectionalAngle); } } // namespace const char* motionClassificationToString(MotionClassification classification) { Loading Loading @@ -187,7 +200,7 @@ vec2 transformWithoutTranslation(const ui::Transform& transform, const vec2& xy) return roundTransformedCoords(transformedXy - transformedOrigin); } float transformAngle(const ui::Transform& transform, float angleRadians) { float transformAngle(const ui::Transform& transform, float angleRadians, bool isDirectional) { // Construct and transform a vector oriented at the specified clockwise angle from vertical. // Coordinate system: down is increasing Y, right is increasing X. float x = sinf(angleRadians); Loading @@ -201,6 +214,11 @@ float transformAngle(const ui::Transform& transform, float angleRadians) { transformedPoint.x -= origin.x; transformedPoint.y -= origin.y; if (!isDirectional && transformedPoint.y > 0) { // Limit the range of atan2f to [-pi/2, pi/2] by reversing the direction of the vector. transformedPoint *= -1; } // Derive the transformed vector's clockwise angle from vertical. // The return value of atan2f is in range [-pi, pi] which conforms to the orientation API. return atan2f(transformedPoint.x, -transformedPoint.y); Loading Loading @@ -530,7 +548,7 @@ bool PointerCoords::operator==(const PointerCoords& other) const { return true; } void PointerCoords::transform(const ui::Transform& transform) { void PointerCoords::transform(const ui::Transform& transform, int32_t motionEventFlags) { const vec2 xy = transform.transform(getXYValue()); setAxisValue(AMOTION_EVENT_AXIS_X, xy.x); setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y); Loading @@ -544,9 +562,9 @@ void PointerCoords::transform(const ui::Transform& transform) { setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); } if (BitSet64::hasBit(bits, AMOTION_EVENT_AXIS_ORIENTATION)) { const float val = getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(transform, val)); if ((motionEventFlags & AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION) != 0) { setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformOrientation(transform, *this, motionEventFlags)); } } Loading Loading @@ -723,13 +741,13 @@ const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { const PointerCoords& coords = *getHistoricalRawPointerCoords(pointerIndex, historicalIndex); return calculateTransformedAxisValue(axis, mSource, mRawTransform, coords); return calculateTransformedAxisValue(axis, mSource, mFlags, mRawTransform, coords); } float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, size_t historicalIndex) const { const PointerCoords& coords = *getHistoricalRawPointerCoords(pointerIndex, historicalIndex); return calculateTransformedAxisValue(axis, mSource, mTransform, coords); return calculateTransformedAxisValue(axis, mSource, mFlags, mTransform, coords); } ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { Loading Loading @@ -787,7 +805,7 @@ void MotionEvent::applyTransform(const std::array<float, 9>& matrix) { // Apply the transformation to all samples. std::for_each(mSamplePointerCoords.begin(), mSamplePointerCoords.end(), [&transform](PointerCoords& c) { c.transform(transform); }); [&](PointerCoords& c) { c.transform(transform, mFlags); }); if (mRawXCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION && mRawYCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) { Loading Loading @@ -1059,7 +1077,7 @@ vec2 MotionEvent::calculateTransformedXY(uint32_t source, const ui::Transform& t } // Keep in sync with calculateTransformedCoords. float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, int32_t flags, const ui::Transform& transform, const PointerCoords& coords) { if (shouldDisregardTransformation(source)) { Loading @@ -1081,7 +1099,7 @@ float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, } if (axis == AMOTION_EVENT_AXIS_ORIENTATION) { return transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION)); return transformOrientation(transform, coords, flags); } return coords.getAxisValue(axis); Loading @@ -1089,7 +1107,7 @@ float MotionEvent::calculateTransformedAxisValue(int32_t axis, uint32_t source, // Keep in sync with calculateTransformedAxisValue. This is an optimization of // calculateTransformedAxisValue for all PointerCoords axes. PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, int32_t flags, const ui::Transform& transform, const PointerCoords& coords) { if (shouldDisregardTransformation(source)) { Loading @@ -1109,8 +1127,7 @@ PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, relativeXy.y); out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(transform, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION))); transformOrientation(transform, coords, flags)); return out; } Loading
libs/input/android/os/IInputConstants.aidl +25 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,31 @@ interface IInputConstants */ const int MOTION_EVENT_FLAG_NO_FOCUS_CHANGE = 0x40; /** * This flag indicates that the event has a valid value for AXIS_ORIENTATION. * * This is a private flag that is not used in Java. * @hide */ const int MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION = 0x80; /** * This flag indicates that the pointers' AXIS_ORIENTATION can be used to precisely determine * the direction in which the tool is pointing. The value of the orientation axis will be in * the range [-pi, pi], which represents a full circle. This is usually supported by devices * like styluses. * * Conversely, AXIS_ORIENTATION cannot be used to tell which direction the tool is pointing * when this flag is not set. In this case, the axis value will have a range of [-pi/2, pi/2], * which represents half a circle. This is usually the case for devices like touchscreens and * touchpads, for which it is difficult to tell which direction along the major axis of the * touch ellipse the finger is pointing. * * This is a private flag that is not used in Java. * @hide */ const int MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = 0x100; /** * The input event was generated or modified by accessibility service. * Shared by both KeyEvent and MotionEvent flags, so this value should not overlap with either Loading
libs/input/tests/InputEvent_test.cpp +125 −14 Original line number Diff line number Diff line Loading @@ -26,23 +26,39 @@ namespace android { namespace { // Default display id. static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT; constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT; static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION; constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION; static constexpr auto POINTER_0_DOWN = constexpr auto POINTER_0_DOWN = AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); static constexpr auto POINTER_1_DOWN = constexpr auto POINTER_1_DOWN = AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); static constexpr auto POINTER_0_UP = constexpr auto POINTER_0_UP = AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); static constexpr auto POINTER_1_UP = constexpr auto POINTER_1_UP = AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); std::array<float, 9> asFloat9(const ui::Transform& t) { std::array<float, 9> mat{}; mat[0] = t[0][0]; mat[1] = t[1][0]; mat[2] = t[2][0]; mat[3] = t[0][1]; mat[4] = t[1][1]; mat[5] = t[2][1]; mat[6] = t[0][2]; mat[7] = t[1][2]; mat[8] = t[2][2]; return mat; } class BaseTest : public testing::Test { protected: static constexpr std::array<uint8_t, 32> HMAC = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, Loading @@ -50,6 +66,8 @@ protected: 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; }; } // namespace // --- PointerCoordsTest --- class PointerCoordsTest : public BaseTest { Loading Loading @@ -344,13 +362,15 @@ void MotionEventTest::SetUp() { } void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION; event->initialize(mId, 2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, HMAC, AMOTION_EVENT_ACTION_MOVE, 0, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE, mTransform, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, mRawTransform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, mPointerProperties, mSamples[0].pointerCoords); AMOTION_EVENT_ACTION_MOVE, 0, flags, AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE, mTransform, 2.0f, 2.1f, AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION, mRawTransform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, mPointerProperties, mSamples[0].pointerCoords); event->addSample(ARBITRARY_EVENT_TIME + 1, mSamples[1].pointerCoords); event->addSample(ARBITRARY_EVENT_TIME + 2, mSamples[2].pointerCoords); } Loading @@ -364,7 +384,10 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { ASSERT_EQ(DISPLAY_ID, event->getDisplayId()); EXPECT_EQ(HMAC, event->getHmac()); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction()); ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags()); ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION, event->getFlags()); ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags()); ASSERT_EQ(AMETA_ALT_ON, event->getMetaState()); ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState()); Loading Loading @@ -799,8 +822,10 @@ TEST_F(MotionEventTest, Transform) { } MotionEvent event; ui::Transform identityTransform; const int32_t flags = AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION; event.initialize(InputEvent::nextId(), /*deviceId=*/0, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, /*actionButton=*/0, /*flags=*/0, INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, /*actionButton=*/0, flags, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE, identityTransform, /*xPrecision=*/0, /*yPrecision=*/0, /*xCursorPosition=*/3 + RADIUS, /*yCursorPosition=*/2, Loading Loading @@ -1087,4 +1112,90 @@ TEST_F(MotionEventTest, CoordinatesAreRoundedAppropriately) { ASSERT_EQ(EXPECTED.y, event.getYCursorPosition()); } TEST_F(MotionEventTest, InvalidOrientationNotRotated) { // This touch event does not have a value for AXIS_ORIENTATION, and the flags are implicitly // set to 0. The transform is set to a 90-degree rotation. MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) .downTime(ARBITRARY_DOWN_TIME) .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4)) .transform(ui::Transform(ui::Transform::ROT_90, 100, 100)) .rawTransform(ui::Transform(ui::Transform::FLIP_H, 50, 50)) .build(); ASSERT_EQ(event.getOrientation(/*pointerIndex=*/0), 0.f); event.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); ASSERT_EQ(event.getOrientation(/*pointerIndex=*/0), 0.f); event.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); ASSERT_EQ(event.getOrientation(/*pointerIndex=*/0), 0.f); event.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); ASSERT_EQ(event.getOrientation(/*pointerIndex=*/0), 0.f); } TEST_F(MotionEventTest, ValidZeroOrientationRotated) { // This touch events will implicitly have a value of 0 for its AXIS_ORIENTATION. auto builder = MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) .downTime(ARBITRARY_DOWN_TIME) .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER).x(4).y(4)) .transform(ui::Transform(ui::Transform::ROT_90, 100, 100)) .rawTransform(ui::Transform(ui::Transform::FLIP_H, 50, 50)) .addFlag(AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION); MotionEvent nonDirectionalEvent = builder.build(); MotionEvent directionalEvent = builder.addFlag(AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION).build(); // The angle is rotated by the initial transform, a 90-degree rotation. ASSERT_NEAR(fabs(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0)), M_PI_2, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), M_PI_2, EPSILON); nonDirectionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); directionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), 0.f, EPSILON); ASSERT_NEAR(fabs(directionalEvent.getOrientation(/*pointerIndex=*/0)), M_PI, EPSILON); nonDirectionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); directionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), 0.f, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), 0.f, EPSILON); nonDirectionalEvent.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); directionalEvent.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); ASSERT_NEAR(fabs(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0)), M_PI_2, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), -M_PI_2, EPSILON); } TEST_F(MotionEventTest, ValidNonZeroOrientationRotated) { const float initial = 1.f; auto builder = MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) .downTime(ARBITRARY_DOWN_TIME) .pointer(PointerBuilder(/*id=*/4, ToolType::FINGER) .x(4) .y(4) .axis(AMOTION_EVENT_AXIS_ORIENTATION, initial)) .transform(ui::Transform(ui::Transform::ROT_90, 100, 100)) .rawTransform(ui::Transform(ui::Transform::FLIP_H, 50, 50)) .addFlag(AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION); MotionEvent nonDirectionalEvent = builder.build(); MotionEvent directionalEvent = builder.addFlag(AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION).build(); // The angle is rotated by the initial transform, a 90-degree rotation. ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), initial - M_PI_2, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), initial + M_PI_2, EPSILON); nonDirectionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); directionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_90, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), initial, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), initial - M_PI, EPSILON); nonDirectionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); directionalEvent.transform(asFloat9(ui::Transform(ui::Transform::ROT_180, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), initial, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), initial, EPSILON); nonDirectionalEvent.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); directionalEvent.applyTransform(asFloat9(ui::Transform(ui::Transform::ROT_270, 100, 100))); ASSERT_NEAR(nonDirectionalEvent.getOrientation(/*pointerIndex=*/0), initial - M_PI_2, EPSILON); ASSERT_NEAR(directionalEvent.getOrientation(/*pointerIndex=*/0), initial - M_PI_2, EPSILON); } } // namespace android
libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,9 @@ PublishMotionArgs::PublishMotionArgs(int32_t inAction, nsecs_t inDownTime, hmac = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION; if (action == AMOTION_EVENT_ACTION_CANCEL) { flags |= AMOTION_EVENT_FLAG_CANCELED; } Loading