From 3914e57d8bc9d26f47473f6a3d1e989672ac9c1c Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Thu, 25 Nov 2021 10:42:39 -0800 Subject: [PATCH] Add getSurfaceRotation API to MotionEvent Add an API to get the current rotation value of the transform of the MotionEvent. Bug: 207771136 Test: atest MotionEventTest Change-Id: I5ee11e7a0311bdbeefbb37251098ce63b7d22730 --- core/java/android/view/MotionEvent.java | 45 ++++++++++++++----- core/jni/android_view_MotionEvent.cpp | 7 +++ .../src/android/view/MotionEventTest.java | 34 +++++++++++--- 3 files changed, 70 insertions(+), 16 deletions(-) diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 3d57db9051e93..b8e50fc6adf24 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -1663,6 +1663,9 @@ public final class MotionEvent extends InputEvent implements Parcelable { @CriticalNative private static native void nativeScale(long nativePtr, float scale); + @CriticalNative + private static native int nativeGetSurfaceRotation(long nativePtr); + private MotionEvent() { } @@ -3805,17 +3808,39 @@ public final class MotionEvent extends InputEvent implements Parcelable { } /** - * Gets a rotation matrix that (when applied to a motionevent) will rotate that motion event - * such that the result coordinates end up in the same physical location on a display whose - * coordinates are rotated by `rotation`. + * Gets the rotation value of the transform for this MotionEvent. * - * For example, rotating 0,0 by 90 degrees will move a point from the physical top-left to - * the bottom-left of the 90-degree-rotated display. + * This MotionEvent's rotation can be changed by passing a rotation matrix to + * {@link #transform(Matrix)} to change the coordinate space of this event. + * + * @return the rotation value, or -1 if unknown or invalid. + * @see Surface.Rotation + * @see #createRotateMatrix(int, int, int) * * @hide */ + public @Surface.Rotation int getSurfaceRotation() { + return nativeGetSurfaceRotation(mNativePtr); + } + + /** + * Gets a rotation matrix that (when applied to a MotionEvent) will rotate that motion event + * such that the result coordinates end up in the same physical location on a frame whose + * coordinates are rotated by `rotation`. + * + * For example, rotating (0,0) by 90 degrees will move a point from the physical top-left to + * the bottom-left of the 90-degree-rotated frame. + * + * @param rotation the surface rotation of the output matrix + * @param rotatedFrameWidth the width of the rotated frame + * @param rotatedFrameHeight the height of the rotated frame + * + * @see #transform(Matrix) + * @see #getSurfaceRotation() + * @hide + */ public static Matrix createRotateMatrix( - @Surface.Rotation int rotation, int displayW, int displayH) { + @Surface.Rotation int rotation, int rotatedFrameWidth, int rotatedFrameHeight) { if (rotation == Surface.ROTATION_0) { return new Matrix(Matrix.IDENTITY_MATRIX); } @@ -3823,14 +3848,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { float[] values = null; if (rotation == Surface.ROTATION_90) { values = new float[]{0, 1, 0, - -1, 0, displayH, + -1, 0, rotatedFrameHeight, 0, 0, 1}; } else if (rotation == Surface.ROTATION_180) { - values = new float[]{-1, 0, displayW, - 0, -1, displayH, + values = new float[]{-1, 0, rotatedFrameWidth, + 0, -1, rotatedFrameHeight, 0, 0, 1}; } else if (rotation == Surface.ROTATION_270) { - values = new float[]{0, -1, displayW, + values = new float[]{0, -1, rotatedFrameWidth, 1, 0, 0, 0, 0, 1}; } diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp index 292f30510aa0f..07e1a6c4e3a78 100644 --- a/core/jni/android_view_MotionEvent.cpp +++ b/core/jni/android_view_MotionEvent.cpp @@ -769,6 +769,11 @@ static void android_view_MotionEvent_nativeScale(jlong nativePtr, jfloat scale) event->scale(scale); } +static jint android_view_MotionEvent_nativeGetSurfaceRotation(jlong nativePtr) { + MotionEvent* event = reinterpret_cast(nativePtr); + return jint(event->getSurfaceRotation()); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gMotionEventMethods[] = { @@ -845,6 +850,8 @@ static const JNINativeMethod gMotionEventMethods[] = { {"nativeFindPointerIndex", "(JI)I", (void*)android_view_MotionEvent_nativeFindPointerIndex}, {"nativeGetHistorySize", "(J)I", (void*)android_view_MotionEvent_nativeGetHistorySize}, {"nativeScale", "(JF)V", (void*)android_view_MotionEvent_nativeScale}, + {"nativeGetSurfaceRotation", "(J)I", + (void*)android_view_MotionEvent_nativeGetSurfaceRotation}, }; int register_android_view_MotionEvent(JNIEnv* env) { diff --git a/core/tests/coretests/src/android/view/MotionEventTest.java b/core/tests/coretests/src/android/view/MotionEventTest.java index 7f7a7aaf73058..78a8f7b3f32e5 100644 --- a/core/tests/coretests/src/android/view/MotionEventTest.java +++ b/core/tests/coretests/src/android/view/MotionEventTest.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import android.graphics.Matrix; import android.platform.test.annotations.Presubmit; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; @@ -174,22 +175,43 @@ public class MotionEventTest { @Test public void testEventRotation() { + // The un-rotated frame size. + final int width = 600; + final int height = 1000; final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */, - ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */); + ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */); event.setSource(InputDevice.SOURCE_TOUCHSCREEN); + assertEquals(Surface.ROTATION_0, event.getSurfaceRotation()); + MotionEvent rot90 = MotionEvent.obtain(event); - rot90.transform(MotionEvent.createRotateMatrix(/* 90 deg */1, 1000, 600)); + rot90.transform(MotionEvent.createRotateMatrix(Surface.ROTATION_90, height, width)); assertEquals(50, (int) rot90.getX()); assertEquals(570, (int) rot90.getY()); + assertEquals(Surface.ROTATION_90, rot90.getSurfaceRotation()); MotionEvent rot180 = MotionEvent.obtain(event); - rot180.transform(MotionEvent.createRotateMatrix(/* 180 deg */2, 1000, 600)); - assertEquals(970, (int) rot180.getX()); - assertEquals(550, (int) rot180.getY()); + rot180.transform(MotionEvent.createRotateMatrix(Surface.ROTATION_180, width, height)); + assertEquals(570, (int) rot180.getX()); + assertEquals(950, (int) rot180.getY()); + assertEquals(Surface.ROTATION_180, rot180.getSurfaceRotation()); MotionEvent rot270 = MotionEvent.obtain(event); - rot270.transform(MotionEvent.createRotateMatrix(/* 270 deg */3, 1000, 600)); + rot270.transform(MotionEvent.createRotateMatrix(Surface.ROTATION_270, height, width)); assertEquals(950, (int) rot270.getX()); assertEquals(30, (int) rot270.getY()); + assertEquals(Surface.ROTATION_270, rot270.getSurfaceRotation()); + + MotionEvent compoundRot = MotionEvent.obtain(event); + compoundRot.transform(MotionEvent.createRotateMatrix(Surface.ROTATION_90, height, width)); + compoundRot.transform(MotionEvent.createRotateMatrix(Surface.ROTATION_180, height, width)); + assertEquals(950, (int) compoundRot.getX()); + assertEquals(30, (int) compoundRot.getY()); + assertEquals(Surface.ROTATION_270, compoundRot.getSurfaceRotation()); + + MotionEvent rotInvalid = MotionEvent.obtain(event); + Matrix mat = new Matrix(); + mat.setValues(new float[]{1, 2, 3, -4, -5, -6, 0, 0, 1}); + rotInvalid.transform(mat); + assertEquals(-1, rotInvalid.getSurfaceRotation()); } }