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
This commit is contained in:
Prabir Pradhan
2021-11-25 10:42:39 -08:00
parent 0d3682ba0b
commit 3914e57d8b
3 changed files with 70 additions and 16 deletions

View File

@@ -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};
}

View File

@@ -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<MotionEvent*>(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) {

View File

@@ -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());
}
}