1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view.cts; 18 19 import static android.view.cts.MotionEventUtils.withCoords; 20 import static android.view.cts.MotionEventUtils.withProperties; 21 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertNotNull; 25 import static org.junit.Assert.assertTrue; 26 import static org.junit.Assert.fail; 27 28 import android.graphics.Matrix; 29 import android.os.Parcel; 30 import android.os.Parcelable; 31 import android.os.SystemClock; 32 import android.text.TextUtils; 33 import android.view.InputDevice; 34 import android.view.KeyEvent; 35 import android.view.MotionEvent; 36 import android.view.MotionEvent.PointerCoords; 37 import android.view.MotionEvent.PointerProperties; 38 import android.view.cts.MotionEventUtils.PointerCoordsBuilder; 39 import android.view.cts.MotionEventUtils.PointerPropertiesBuilder; 40 41 import androidx.test.filters.SmallTest; 42 import androidx.test.runner.AndroidJUnit4; 43 44 import org.junit.After; 45 import org.junit.Before; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 49 import java.util.LinkedHashSet; 50 import java.util.Set; 51 52 /** 53 * Test {@link MotionEvent}. 54 */ 55 @SmallTest 56 @RunWith(AndroidJUnit4.class) 57 public class MotionEventTest { 58 private MotionEvent mMotionEvent1; 59 private MotionEvent mMotionEvent2; 60 private MotionEvent mMotionEventDynamic; 61 private long mDownTime; 62 private long mEventTime; 63 private long mEventTimeNano; 64 private static final int NS_PER_MS = 1_000_000; 65 private static final float X_3F = 3.0f; 66 private static final float Y_4F = 4.0f; 67 private static final int META_STATE = KeyEvent.META_SHIFT_ON; 68 private static final float PRESSURE_1F = 1.0f; 69 private static final float SIZE_1F = 1.0f; 70 private static final float X_PRECISION_3F = 3.0f; 71 private static final float Y_PRECISION_4F = 4.0f; 72 private static final int DEVICE_ID_1 = 1; 73 private static final int EDGE_FLAGS = MotionEvent.EDGE_TOP; 74 private static final float DELTA = 0.01f; 75 private static final float RAW_COORD_TOLERANCE = 0.001f; 76 nativeMotionEventTest(MotionEvent event)77 private static native void nativeMotionEventTest(MotionEvent event); 78 79 static { 80 System.loadLibrary("ctsview_jni"); 81 } 82 83 @Before setup()84 public void setup() { 85 mDownTime = SystemClock.uptimeMillis(); 86 mEventTime = SystemClock.uptimeMillis(); 87 mEventTimeNano = mEventTime * NS_PER_MS; 88 mMotionEvent1 = MotionEvent.obtain(mDownTime, mEventTime, 89 MotionEvent.ACTION_MOVE, X_3F, Y_4F, META_STATE); 90 mMotionEvent2 = MotionEvent.obtain(mDownTime, mEventTime, 91 MotionEvent.ACTION_MOVE, X_3F, Y_4F, PRESSURE_1F, SIZE_1F, META_STATE, 92 X_PRECISION_3F, Y_PRECISION_4F, DEVICE_ID_1, EDGE_FLAGS); 93 } 94 95 @After teardown()96 public void teardown() { 97 if (null != mMotionEvent1) { 98 mMotionEvent1.recycle(); 99 } 100 if (null != mMotionEvent2) { 101 mMotionEvent2.recycle(); 102 } 103 if (null != mMotionEventDynamic) { 104 mMotionEventDynamic.recycle(); 105 } 106 } 107 108 @Test testObtainBasic()109 public void testObtainBasic() { 110 mMotionEvent1 = MotionEvent.obtain(mDownTime, mEventTime, 111 MotionEvent.ACTION_DOWN, X_3F, Y_4F, META_STATE); 112 assertNotNull(mMotionEvent1); 113 assertEquals(mDownTime, mMotionEvent1.getDownTime()); 114 assertEquals(mEventTime, mMotionEvent1.getEventTime()); 115 assertEquals(mEventTimeNano, mMotionEvent1.getEventTimeNanos()); 116 assertEquals(MotionEvent.ACTION_DOWN, mMotionEvent1.getAction()); 117 assertEquals(X_3F, mMotionEvent1.getX(), DELTA); 118 assertEquals(Y_4F, mMotionEvent1.getY(), DELTA); 119 assertEquals(X_3F, mMotionEvent1.getRawX(), DELTA); 120 assertEquals(Y_4F, mMotionEvent1.getRawY(), DELTA); 121 assertEquals(META_STATE, mMotionEvent1.getMetaState()); 122 assertEquals(0, mMotionEvent1.getDeviceId()); 123 assertEquals(0, mMotionEvent1.getEdgeFlags()); 124 assertEquals(PRESSURE_1F, mMotionEvent1.getPressure(), DELTA); 125 assertEquals(SIZE_1F, mMotionEvent1.getSize(), DELTA); 126 assertEquals(1.0f, mMotionEvent1.getXPrecision(), DELTA); 127 assertEquals(1.0f, mMotionEvent1.getYPrecision(), DELTA); 128 } 129 130 @Test testObtainFromMotionEvent()131 public void testObtainFromMotionEvent() { 132 mMotionEventDynamic = MotionEvent.obtain(mMotionEvent2); 133 assertNotNull(mMotionEventDynamic); 134 assertEquals(mMotionEvent2.getDownTime(), mMotionEventDynamic.getDownTime()); 135 assertEquals(mMotionEvent2.getEventTime(), mMotionEventDynamic.getEventTime()); 136 assertEquals(mMotionEvent2.getEventTimeNanos(), mMotionEventDynamic.getEventTimeNanos()); 137 assertEquals(mMotionEvent2.getAction(), mMotionEventDynamic.getAction()); 138 assertEquals(mMotionEvent2.getX(), mMotionEventDynamic.getX(), DELTA); 139 assertEquals(mMotionEvent2.getY(), mMotionEventDynamic.getY(), DELTA); 140 assertEquals(mMotionEvent2.getX(), mMotionEventDynamic.getRawX(), DELTA); 141 assertEquals(mMotionEvent2.getY(), mMotionEventDynamic.getRawY(), DELTA); 142 assertEquals(mMotionEvent2.getMetaState(), mMotionEventDynamic.getMetaState()); 143 assertEquals(mMotionEvent2.getDeviceId(), mMotionEventDynamic.getDeviceId()); 144 assertEquals(mMotionEvent2.getEdgeFlags(), mMotionEventDynamic.getEdgeFlags()); 145 assertEquals(mMotionEvent2.getPressure(), mMotionEventDynamic.getPressure(), DELTA); 146 assertEquals(mMotionEvent2.getSize(), mMotionEventDynamic.getSize(), DELTA); 147 assertEquals(mMotionEvent2.getXPrecision(), mMotionEventDynamic.getXPrecision(), DELTA); 148 assertEquals(mMotionEvent2.getYPrecision(), mMotionEventDynamic.getYPrecision(), DELTA); 149 } 150 151 @Test testObtainAllFields()152 public void testObtainAllFields() { 153 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 154 MotionEvent.ACTION_DOWN, X_3F, Y_4F, PRESSURE_1F, SIZE_1F, META_STATE, 155 X_PRECISION_3F, Y_PRECISION_4F, DEVICE_ID_1, EDGE_FLAGS); 156 assertNotNull(mMotionEventDynamic); 157 assertEquals(mDownTime, mMotionEventDynamic.getDownTime()); 158 assertEquals(mEventTime, mMotionEventDynamic.getEventTime()); 159 assertEquals(mEventTimeNano, mMotionEventDynamic.getEventTimeNanos()); 160 assertEquals(MotionEvent.ACTION_DOWN, mMotionEventDynamic.getAction()); 161 assertEquals(X_3F, mMotionEventDynamic.getX(), DELTA); 162 assertEquals(Y_4F, mMotionEventDynamic.getY(), DELTA); 163 assertEquals(X_3F, mMotionEventDynamic.getRawX(), DELTA); 164 assertEquals(Y_4F, mMotionEventDynamic.getRawY(), DELTA); 165 assertEquals(META_STATE, mMotionEventDynamic.getMetaState()); 166 assertEquals(DEVICE_ID_1, mMotionEventDynamic.getDeviceId()); 167 assertEquals(EDGE_FLAGS, mMotionEventDynamic.getEdgeFlags()); 168 assertEquals(PRESSURE_1F, mMotionEventDynamic.getPressure(), DELTA); 169 assertEquals(SIZE_1F, mMotionEventDynamic.getSize(), DELTA); 170 assertEquals(X_PRECISION_3F, mMotionEventDynamic.getXPrecision(), DELTA); 171 assertEquals(Y_PRECISION_4F, mMotionEventDynamic.getYPrecision(), DELTA); 172 } 173 174 @Test testObtainFromPropertyArrays()175 public void testObtainFromPropertyArrays() { 176 PointerCoordsBuilder coordsBuilder0 = 177 withCoords(X_3F, Y_4F).withPressure(PRESSURE_1F).withSize(SIZE_1F). 178 withTool(1.2f, 1.4f).withGenericAxis1(2.6f); 179 PointerCoordsBuilder coordsBuilder1 = 180 withCoords(X_3F + 1.0f, Y_4F - 2.0f).withPressure(PRESSURE_1F + 0.2f). 181 withSize(SIZE_1F + 0.5f).withTouch(2.2f, 0.6f).withGenericAxis1(2.6f); 182 183 PointerPropertiesBuilder propertiesBuilder0 = 184 withProperties(0, MotionEvent.TOOL_TYPE_FINGER); 185 PointerPropertiesBuilder propertiesBuilder1 = 186 withProperties(1, MotionEvent.TOOL_TYPE_FINGER); 187 188 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 189 MotionEvent.ACTION_MOVE, 2, 190 new PointerProperties[] { propertiesBuilder0.build(), propertiesBuilder1.build() }, 191 new PointerCoords[] { coordsBuilder0.build(), coordsBuilder1.build() }, 192 META_STATE, 0, X_PRECISION_3F, Y_PRECISION_4F, DEVICE_ID_1, EDGE_FLAGS, 193 InputDevice.SOURCE_TOUCHSCREEN, 0); 194 195 // We expect to have data for two pointers 196 assertEquals(2, mMotionEventDynamic.getPointerCount()); 197 assertEquals(0, mMotionEventDynamic.getPointerId(0)); 198 assertEquals(1, mMotionEventDynamic.getPointerId(1)); 199 assertEquals(0, mMotionEventDynamic.getFlags()); 200 verifyCurrentPointerData(mMotionEventDynamic, 201 new PointerPropertiesBuilder[] { propertiesBuilder0, propertiesBuilder1 }, 202 new PointerCoordsBuilder[] { coordsBuilder0, coordsBuilder1 }); 203 } 204 205 @Test testObtainWithClassification()206 public void testObtainWithClassification() { 207 PointerCoordsBuilder coordsBuilder = 208 withCoords(X_3F, Y_4F).withPressure(PRESSURE_1F).withSize(SIZE_1F) 209 .withTool(1.2f, 1.4f).withGenericAxis1(2.6f); 210 PointerPropertiesBuilder propertiesBuilder = 211 withProperties(0, MotionEvent.TOOL_TYPE_FINGER); 212 213 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 214 MotionEvent.ACTION_MOVE, 1, 215 new PointerProperties[] { propertiesBuilder.build() }, 216 new PointerCoords[] { coordsBuilder.build() }, 217 META_STATE, 0, X_PRECISION_3F, Y_PRECISION_4F, DEVICE_ID_1, EDGE_FLAGS, 218 InputDevice.SOURCE_TOUCHSCREEN, 0, 0, MotionEvent.CLASSIFICATION_DEEP_PRESS); 219 assertEquals(MotionEvent.CLASSIFICATION_DEEP_PRESS, 220 mMotionEventDynamic.getClassification()); 221 } 222 223 @Test testObtainNoHistory()224 public void testObtainNoHistory() { 225 // Add two batch to one of our events 226 mMotionEvent2.addBatch(mEventTime + 10, X_3F + 5.0f, Y_4F + 5.0f, 0.5f, 0.5f, 0); 227 mMotionEvent2.addBatch(mEventTime + 20, X_3F + 10.0f, Y_4F + 15.0f, 2.0f, 3.0f, 0); 228 // The newly added batch should be the "new" values of the event 229 withCoords(X_3F + 10.0f, Y_4F + 15.0f).withPressure(2.0f).withSize(3.0f). 230 verifyMatches(mMotionEvent2); 231 assertEquals(mEventTime + 20, mMotionEvent2.getEventTime()); 232 assertEquals((mEventTime + 20) * NS_PER_MS, mMotionEvent2.getEventTimeNanos()); 233 // We should have history with 2 entries 234 assertEquals(2, mMotionEvent2.getHistorySize()); 235 // The previous data should be history at index 1 236 withCoords(X_3F + 5.0f, Y_4F + 5.0f).withPressure(0.5f).withSize(0.5f). 237 verifyMatchesHistorical(mMotionEvent2, 1); 238 assertEquals(mEventTime + 10, mMotionEvent2.getHistoricalEventTime(1)); 239 assertEquals((mEventTime + 10) * NS_PER_MS, mMotionEvent2.getHistoricalEventTimeNanos(1)); 240 // And the original data should be history at index 0 241 withCoords(X_3F, Y_4F).withPressure(1.0f).withSize(1.0f). 242 verifyMatchesHistorical(mMotionEvent2, 0); 243 assertEquals(mEventTime, mMotionEvent2.getHistoricalEventTime(0)); 244 assertEquals(mEventTimeNano, mMotionEvent2.getHistoricalEventTimeNanos(0)); 245 246 assertEquals(2, mMotionEvent2.getHistorySize()); 247 248 mMotionEventDynamic = MotionEvent.obtainNoHistory(mMotionEvent2); 249 // The newly obtained event should have the matching current content 250 withCoords(X_3F + 10.0f, Y_4F + 15.0f).withPressure(2.0f).withSize(3.0f). 251 verifyMatches(mMotionEvent2); 252 // And no history 253 assertEquals(0, mMotionEventDynamic.getHistorySize()); 254 } 255 256 @Test testAccessAction()257 public void testAccessAction() { 258 assertEquals(MotionEvent.ACTION_MOVE, mMotionEvent1.getAction()); 259 260 mMotionEvent1.setAction(MotionEvent.ACTION_UP); 261 assertEquals(MotionEvent.ACTION_UP, mMotionEvent1.getAction()); 262 263 mMotionEvent1.setAction(MotionEvent.ACTION_MOVE); 264 assertEquals(MotionEvent.ACTION_MOVE, mMotionEvent1.getAction()); 265 266 mMotionEvent1.setAction(MotionEvent.ACTION_CANCEL); 267 assertEquals(MotionEvent.ACTION_CANCEL, mMotionEvent1.getAction()); 268 269 mMotionEvent1.setAction(MotionEvent.ACTION_DOWN); 270 assertEquals(MotionEvent.ACTION_DOWN, mMotionEvent1.getAction()); 271 } 272 273 @Test testDescribeContents()274 public void testDescribeContents() { 275 // make sure this method never throw any exception. 276 mMotionEvent2.describeContents(); 277 } 278 279 @Test testAccessEdgeFlags()280 public void testAccessEdgeFlags() { 281 assertEquals(EDGE_FLAGS, mMotionEvent2.getEdgeFlags()); 282 283 int edgeFlags = 10; 284 mMotionEvent2.setEdgeFlags(edgeFlags); 285 assertEquals(edgeFlags, mMotionEvent2.getEdgeFlags()); 286 } 287 288 @Test testWriteToParcel()289 public void testWriteToParcel() { 290 Parcel parcel = Parcel.obtain(); 291 mMotionEvent2.writeToParcel(parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 292 parcel.setDataPosition(0); 293 294 MotionEvent motionEvent = MotionEvent.CREATOR.createFromParcel(parcel); 295 assertEquals(mMotionEvent2.getRawY(), motionEvent.getRawY(), DELTA); 296 assertEquals(mMotionEvent2.getRawX(), motionEvent.getRawX(), DELTA); 297 assertEquals(mMotionEvent2.getY(), motionEvent.getY(), DELTA); 298 assertEquals(mMotionEvent2.getX(), motionEvent.getX(), DELTA); 299 assertEquals(mMotionEvent2.getAction(), motionEvent.getAction()); 300 assertEquals(mMotionEvent2.getDownTime(), motionEvent.getDownTime()); 301 assertEquals(mMotionEvent2.getEventTime(), motionEvent.getEventTime()); 302 assertEquals(mMotionEvent2.getEventTimeNanos(), motionEvent.getEventTimeNanos()); 303 assertEquals(mMotionEvent2.getEdgeFlags(), motionEvent.getEdgeFlags()); 304 assertEquals(mMotionEvent2.getDeviceId(), motionEvent.getDeviceId()); 305 } 306 307 @Test testReadFromParcelWithInvalidPointerCountSize()308 public void testReadFromParcelWithInvalidPointerCountSize() { 309 Parcel parcel = Parcel.obtain(); 310 mMotionEvent2.writeToParcel(parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 311 312 // Move to pointer id count. 313 parcel.setDataPosition(4); 314 parcel.writeInt(17); 315 316 parcel.setDataPosition(0); 317 try { 318 MotionEvent.CREATOR.createFromParcel(parcel); 319 fail("deserialized invalid parcel"); 320 } catch (RuntimeException e) { 321 // Expected. 322 } 323 } 324 325 @Test testReadFromParcelWithInvalidSampleSize()326 public void testReadFromParcelWithInvalidSampleSize() { 327 Parcel parcel = Parcel.obtain(); 328 mMotionEvent2.writeToParcel(parcel, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); 329 330 // Move to sample count. 331 parcel.setDataPosition(2 * 4); 332 parcel.writeInt(0x000f0000); 333 334 parcel.setDataPosition(0); 335 try { 336 MotionEvent.CREATOR.createFromParcel(parcel); 337 fail("deserialized invalid parcel"); 338 } catch (RuntimeException e) { 339 // Expected. 340 } 341 } 342 343 @SuppressWarnings("ReturnValueIgnored") 344 @Test testToString()345 public void testToString() { 346 // make sure this method never throw exception. 347 mMotionEvent2.toString(); 348 } 349 350 @Test testOffsetLocationForPointerSource()351 public void testOffsetLocationForPointerSource() { 352 assertEquals(X_3F, mMotionEvent2.getX(), DELTA); 353 assertEquals(Y_4F, mMotionEvent2.getY(), DELTA); 354 mMotionEvent2.setSource(InputDevice.SOURCE_TOUCHSCREEN); 355 356 float offsetX = 1.0f; 357 float offsetY = 1.0f; 358 mMotionEvent2.offsetLocation(offsetX, offsetY); 359 withCoords(X_3F + offsetX, Y_4F + offsetY) 360 .withPressure(PRESSURE_1F) 361 .withSize(SIZE_1F) 362 .verifyMatches(mMotionEvent2); 363 } 364 365 @Test testNoLocationOffsetForNonPointerSource()366 public void testNoLocationOffsetForNonPointerSource() { 367 assertEquals(X_3F, mMotionEvent2.getX(), DELTA); 368 assertEquals(Y_4F, mMotionEvent2.getY(), DELTA); 369 mMotionEvent2.setSource(InputDevice.SOURCE_TOUCHPAD); 370 371 float offsetX = 1.0f; 372 float offsetY = 1.0f; 373 mMotionEvent2.offsetLocation(offsetX, offsetY); 374 withCoords(X_3F, Y_4F) 375 .withPressure(PRESSURE_1F) 376 .withSize(SIZE_1F) 377 .verifyMatches(mMotionEvent2); 378 } 379 380 @Test testSetLocation()381 public void testSetLocation() { 382 assertEquals(X_3F, mMotionEvent2.getX(), DELTA); 383 assertEquals(Y_4F, mMotionEvent2.getY(), DELTA); 384 mMotionEvent2.setSource(InputDevice.SOURCE_TOUCHSCREEN); 385 386 mMotionEvent2.setLocation(0.0f, 0.0f); 387 withCoords(0.0f, 0.0f).withPressure(PRESSURE_1F).withSize(SIZE_1F). 388 verifyMatches(mMotionEvent2); 389 390 mMotionEvent2.setLocation(2.0f, 2.0f); 391 withCoords(2.0f, 2.0f).withPressure(PRESSURE_1F).withSize(SIZE_1F). 392 verifyMatches(mMotionEvent2); 393 } 394 395 @Test testGetHistoricalData()396 public void testGetHistoricalData() { 397 assertEquals(0, mMotionEvent2.getHistorySize()); 398 399 mMotionEvent2.addBatch(mEventTime + 10, X_3F + 5.0f, Y_4F + 5.0f, 0.5f, 0.5f, 0); 400 // The newly added batch should be the "new" values of the event 401 withCoords(X_3F + 5.0f, Y_4F + 5.0f).withPressure(0.5f).withSize(0.5f). 402 verifyMatches(mMotionEvent2); 403 assertEquals(mEventTime + 10, mMotionEvent2.getEventTime()); 404 assertEquals((mEventTime + 10) * NS_PER_MS, mMotionEvent2.getEventTimeNanos()); 405 // We should have history with 1 entry 406 assertEquals(1, mMotionEvent2.getHistorySize()); 407 // And the previous / original data should be history at index 0 408 assertEquals(1, mMotionEvent2.getHistorySize()); 409 withCoords(X_3F, Y_4F).withPressure(1.0f).withSize(1.0f). 410 verifyMatchesHistorical(mMotionEvent2, 0); 411 assertEquals(mEventTime, mMotionEvent2.getHistoricalEventTime(0)); 412 assertEquals(mEventTimeNano, mMotionEvent2.getHistoricalEventTimeNanos(0)); 413 414 // Add another update batch to our event 415 mMotionEvent2.addBatch(mEventTime + 20, X_3F + 10.0f, Y_4F + 15.0f, 2.0f, 3.0f, 0); 416 // The newly added batch should be the "new" values of the event 417 withCoords(X_3F + 10.0f, Y_4F + 15.0f).withPressure(2.0f).withSize(3.0f). 418 verifyMatches(mMotionEvent2); 419 assertEquals(mEventTime + 20, mMotionEvent2.getEventTime()); 420 assertEquals((mEventTime + 20) * NS_PER_MS, mMotionEvent2.getEventTimeNanos()); 421 // We should have history with 2 entries 422 assertEquals(2, mMotionEvent2.getHistorySize()); 423 // The previous data should be history at index 1 424 withCoords(X_3F + 5.0f, Y_4F + 5.0f).withPressure(0.5f).withSize(0.5f). 425 verifyMatchesHistorical(mMotionEvent2, 1); 426 assertEquals(mEventTime + 10, mMotionEvent2.getHistoricalEventTime(1)); 427 assertEquals((mEventTime + 10) * NS_PER_MS, mMotionEvent2.getHistoricalEventTimeNanos(1)); 428 // And the original data should be history at index 0 429 withCoords(X_3F, Y_4F).withPressure(1.0f).withSize(1.0f). 430 verifyMatchesHistorical(mMotionEvent2, 0); 431 assertEquals(mEventTime, mMotionEvent2.getHistoricalEventTime(0)); 432 assertEquals(mEventTimeNano, mMotionEvent2.getHistoricalEventTimeNanos(0)); 433 } 434 verifyCurrentPointerData(MotionEvent motionEvent, PointerPropertiesBuilder[] pointerPropertiesBuilders, PointerCoordsBuilder[] pointerCoordsBuilders)435 private static void verifyCurrentPointerData(MotionEvent motionEvent, 436 PointerPropertiesBuilder[] pointerPropertiesBuilders, 437 PointerCoordsBuilder[] pointerCoordsBuilders) { 438 assertNotNull(motionEvent); 439 assertNotNull(pointerPropertiesBuilders); 440 assertNotNull(pointerCoordsBuilders); 441 final int pointerCount = motionEvent.getPointerCount(); 442 assertEquals(pointerCount, pointerPropertiesBuilders.length); 443 assertEquals(pointerCount, pointerCoordsBuilders.length); 444 445 // Test that we have the expected data fetched via MotionEvent.getPointerCoords API 446 for (int i = 0; i < pointerCount; i++) { 447 pointerCoordsBuilders[i].verifyMatchesPointerCoords(motionEvent, i); 448 } 449 450 // Test that we have the expected data fetched via per-field MotionEvent getter APIs 451 for (int i = 0; i < pointerCount; i++) { 452 pointerCoordsBuilders[i].verifyMatches(motionEvent, i); 453 } 454 455 // Test that we have the expected data fetched via MotionEvent.getPointerProperties API 456 for (int i = 0; i < pointerCount; i++) { 457 pointerPropertiesBuilders[i].verifyMatchesPointerProperties(motionEvent, i); 458 } 459 460 // Test that we have the expected data fetched via per-field MotionEvent getter APIs 461 for (int i = 0; i < pointerCount; i++) { 462 pointerPropertiesBuilders[i].verifyMatches(motionEvent, i); 463 } 464 } 465 verifyHistoricalPointerData(MotionEvent motionEvent, PointerCoordsBuilder[] pointerCoordsBuilders, int pos)466 private static void verifyHistoricalPointerData(MotionEvent motionEvent, 467 PointerCoordsBuilder[] pointerCoordsBuilders, int pos) { 468 assertNotNull(motionEvent); 469 assertNotNull(pointerCoordsBuilders); 470 final int pointerCount = motionEvent.getPointerCount(); 471 assertEquals(pointerCount, pointerCoordsBuilders.length); 472 473 // Test that we have the expected data fetched via MotionEvent.getHistoricalPointerCoords 474 // API 475 for (int i = 0; i < pointerCount; i++) { 476 pointerCoordsBuilders[i].verifyMatchesHistoricalPointerCoords(motionEvent, i, pos); 477 } 478 479 // Test that we have the expected data fetched via per-field MotionEvent getter APIs 480 for (int i = 0; i < pointerCount; i++) { 481 pointerCoordsBuilders[i].verifyMatchesHistorical(motionEvent, i, pos); 482 } 483 } 484 485 @Test testGetCurrentDataWithTwoPointers()486 public void testGetCurrentDataWithTwoPointers() { 487 PointerCoordsBuilder coordsBuilder0 = 488 withCoords(10.0f, 20.0f).withPressure(1.2f).withSize(2.0f).withTool(1.2f, 489 1.4f).withGenericAxis1(4.4f); 490 PointerCoordsBuilder coordsBuilder1 = 491 withCoords(30.0f, 40.0f).withPressure(1.4f).withSize(3.0f).withTouch(2.2f, 492 0.6f).withGenericAxis1(6.6f); 493 494 PointerPropertiesBuilder propertiesBuilder0 = 495 withProperties(0, MotionEvent.TOOL_TYPE_FINGER); 496 PointerPropertiesBuilder propertiesBuilder1 = 497 withProperties(1, MotionEvent.TOOL_TYPE_FINGER); 498 499 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 500 MotionEvent.ACTION_MOVE, 2, 501 new PointerProperties[] { propertiesBuilder0.build(), propertiesBuilder1.build() }, 502 new PointerCoords[] { coordsBuilder0.build(), coordsBuilder1.build() }, 503 0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0); 504 505 // We expect to have data for two pointers 506 assertEquals(2, mMotionEventDynamic.getPointerCount()); 507 assertEquals(0, mMotionEventDynamic.getPointerId(0)); 508 assertEquals(1, mMotionEventDynamic.getPointerId(1)); 509 assertEquals(0, mMotionEventDynamic.getFlags()); 510 verifyCurrentPointerData(mMotionEventDynamic, 511 new PointerPropertiesBuilder[] { propertiesBuilder0, propertiesBuilder1 }, 512 new PointerCoordsBuilder[] { coordsBuilder0, coordsBuilder1 }); 513 } 514 515 /** 516 * Verify we can get raw coordinates for specific pointers using MotionEvent#getRawX(int) and 517 * MotionEvent#getRawY(int). Also verity MotionEvent#getRawX() and MotionEvent#getRawY() 518 * returns the raw coordinates of pointer with pointer index 0. 519 */ 520 @Test testGetRawCoordsWithTwoPointers()521 public void testGetRawCoordsWithTwoPointers() { 522 PointerCoordsBuilder coordsBuilder0 = 523 withCoords(10.0f, 20.0f).withPressure(1.2f).withSize(2.0f).withTool(1.2f, 524 1.4f).withGenericAxis1(4.4f); 525 PointerCoordsBuilder coordsBuilder1 = 526 withCoords(30.0f, 40.0f).withPressure(1.4f).withSize(3.0f).withTouch(2.2f, 527 0.6f).withGenericAxis1(6.6f); 528 529 PointerPropertiesBuilder propertiesBuilder0 = 530 withProperties(0, MotionEvent.TOOL_TYPE_FINGER); 531 PointerPropertiesBuilder propertiesBuilder1 = 532 withProperties(1, MotionEvent.TOOL_TYPE_FINGER); 533 534 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 535 MotionEvent.ACTION_MOVE, 2, 536 new PointerProperties[] { propertiesBuilder0.build(), propertiesBuilder1.build() }, 537 new PointerCoords[] { coordsBuilder0.build(), coordsBuilder1.build() }, 538 0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0); 539 540 assertEquals(10.0f, mMotionEventDynamic.getRawX(), RAW_COORD_TOLERANCE); 541 assertEquals(20.0f, mMotionEventDynamic.getRawY(), RAW_COORD_TOLERANCE); 542 543 // Assert that getRawX returns the results for the first pointer index. 544 assertEquals(mMotionEventDynamic.getRawX(), mMotionEventDynamic.getRawX(0), 545 RAW_COORD_TOLERANCE); 546 assertEquals(mMotionEventDynamic.getRawY(), mMotionEventDynamic.getRawY(0), 547 RAW_COORD_TOLERANCE); 548 549 assertEquals(30.0f, mMotionEventDynamic.getRawX(1), RAW_COORD_TOLERANCE); 550 assertEquals(40.0f, mMotionEventDynamic.getRawY(1), RAW_COORD_TOLERANCE); 551 } 552 553 554 @Test testGetHistoricalDataWithTwoPointers()555 public void testGetHistoricalDataWithTwoPointers() { 556 // PHASE 1 - construct the initial data for the event 557 PointerCoordsBuilder coordsBuilderInitial0 = 558 withCoords(10.0f, 20.0f).withPressure(1.2f).withSize(2.0f).withTool(1.2f, 1.4f). 559 withTouch(0.7f, 0.6f).withOrientation(2.0f).withGenericAxis1(4.4f); 560 PointerCoordsBuilder coordsBuilderInitial1 = 561 withCoords(30.0f, 40.0f).withPressure(1.4f).withSize(3.0f).withTool(1.3f, 1.7f). 562 withTouch(2.7f, 3.6f).withOrientation(1.0f).withGenericAxis1(5.4f); 563 564 PointerPropertiesBuilder propertiesBuilder0 = 565 withProperties(0, MotionEvent.TOOL_TYPE_FINGER); 566 PointerPropertiesBuilder propertiesBuilder1 = 567 withProperties(1, MotionEvent.TOOL_TYPE_FINGER); 568 569 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 570 MotionEvent.ACTION_MOVE, 2, 571 new PointerProperties[] { propertiesBuilder0.build(), propertiesBuilder1.build() }, 572 new PointerCoords[] { 573 coordsBuilderInitial0.build(), coordsBuilderInitial1.build() }, 574 0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0); 575 576 // We expect to have data for two pointers 577 assertEquals(2, mMotionEventDynamic.getPointerCount()); 578 assertEquals(0, mMotionEventDynamic.getPointerId(0)); 579 assertEquals(1, mMotionEventDynamic.getPointerId(1)); 580 assertEquals(0, mMotionEventDynamic.getFlags()); 581 verifyCurrentPointerData(mMotionEventDynamic, 582 new PointerPropertiesBuilder[] { propertiesBuilder0, propertiesBuilder1 }, 583 new PointerCoordsBuilder[] { coordsBuilderInitial0, coordsBuilderInitial1 }); 584 585 // PHASE 2 - add a new batch of data to our event 586 PointerCoordsBuilder coordsBuilderNext0 = 587 withCoords(15.0f, 25.0f).withPressure(1.6f).withSize(2.2f).withTool(1.2f, 1.4f). 588 withTouch(1.0f, 0.9f).withOrientation(2.2f).withGenericAxis1(7.4f); 589 PointerCoordsBuilder coordsBuilderNext1 = 590 withCoords(35.0f, 45.0f).withPressure(1.8f).withSize(3.2f).withTool(1.2f, 1.4f). 591 withTouch(0.7f, 0.6f).withOrientation(2.9f).withGenericAxis1(8.4f); 592 593 mMotionEventDynamic.addBatch(mEventTime + 10, 594 new PointerCoords[] { coordsBuilderNext0.build(), coordsBuilderNext1.build() }, 0); 595 // We still expect to have data for two pointers 596 assertEquals(2, mMotionEventDynamic.getPointerCount()); 597 assertEquals(0, mMotionEventDynamic.getPointerId(0)); 598 assertEquals(1, mMotionEventDynamic.getPointerId(1)); 599 assertEquals(0, mMotionEventDynamic.getFlags()); 600 601 // The newly added batch should be the "new" values of the event 602 verifyCurrentPointerData(mMotionEventDynamic, 603 new PointerPropertiesBuilder[] { propertiesBuilder0, propertiesBuilder1 }, 604 new PointerCoordsBuilder[] { coordsBuilderNext0, coordsBuilderNext1 }); 605 assertEquals(mEventTime + 10, mMotionEventDynamic.getEventTime()); 606 assertEquals((mEventTime + 10) * NS_PER_MS, mMotionEventDynamic.getEventTimeNanos()); 607 // We should have history with 1 entry 608 assertEquals(1, mMotionEventDynamic.getHistorySize()); 609 // And the previous / original data should be history at index 0 610 assertEquals(1, mMotionEventDynamic.getHistorySize()); 611 verifyHistoricalPointerData(mMotionEventDynamic, 612 new PointerCoordsBuilder[] { coordsBuilderInitial0, coordsBuilderInitial1 }, 613 0); 614 615 // PHASE 3 - add one more new batch of data to our event 616 PointerCoordsBuilder coordsBuilderLast0 = 617 withCoords(18.0f, 28.0f).withPressure(1.1f).withSize(2.9f).withTool(1.5f, 1.9f). 618 withTouch(1.2f, 5.0f).withOrientation(3.1f).withGenericAxis1(1.4f); 619 PointerCoordsBuilder coordsBuilderLast1 = 620 withCoords(38.0f, 48.0f).withPressure(1.2f).withSize(2.5f).withTool(0.2f, 0.4f). 621 withTouch(2.7f, 4.6f).withOrientation(0.2f).withGenericAxis1(5.4f); 622 623 mMotionEventDynamic.addBatch(mEventTime + 20, 624 new PointerCoords[] { coordsBuilderLast0.build(), coordsBuilderLast1.build() }, 0); 625 // We still expect to have data for two pointers 626 assertEquals(2, mMotionEventDynamic.getPointerCount()); 627 assertEquals(0, mMotionEventDynamic.getPointerId(0)); 628 assertEquals(1, mMotionEventDynamic.getPointerId(1)); 629 assertEquals(0, mMotionEventDynamic.getFlags()); 630 631 // The newly added batch should be the "new" values of the event 632 verifyCurrentPointerData(mMotionEventDynamic, 633 new PointerPropertiesBuilder[] { propertiesBuilder0, propertiesBuilder1 }, 634 new PointerCoordsBuilder[] { coordsBuilderLast0, coordsBuilderLast1 }); 635 assertEquals(mEventTime + 20, mMotionEventDynamic.getEventTime()); 636 assertEquals((mEventTime + 20) * NS_PER_MS, mMotionEventDynamic.getEventTimeNanos()); 637 // We should have history with 2 entries 638 assertEquals(2, mMotionEventDynamic.getHistorySize()); 639 // The previous data should be history at index 1 640 verifyHistoricalPointerData(mMotionEventDynamic, 641 new PointerCoordsBuilder[] { coordsBuilderNext0, coordsBuilderNext1 }, 642 1); 643 assertEquals(mEventTime + 10, mMotionEventDynamic.getHistoricalEventTime(1)); 644 assertEquals((mEventTime + 10) * NS_PER_MS, 645 mMotionEventDynamic.getHistoricalEventTimeNanos(1)); 646 // And the original data should be history at index 0 647 verifyHistoricalPointerData(mMotionEventDynamic, 648 new PointerCoordsBuilder[] { coordsBuilderInitial0, coordsBuilderInitial1 }, 649 0); 650 assertEquals(mEventTime, mMotionEventDynamic.getHistoricalEventTime(0)); 651 assertEquals(mEventTimeNano, mMotionEventDynamic.getHistoricalEventTimeNanos(0)); 652 } 653 654 @Test testGetHistorySize()655 public void testGetHistorySize() { 656 long eventTime = SystemClock.uptimeMillis(); 657 float x = 10.0f; 658 float y = 20.0f; 659 float pressure = 1.0f; 660 float size = 1.0f; 661 662 mMotionEvent2.setAction(MotionEvent.ACTION_DOWN); 663 assertEquals(0, mMotionEvent2.getHistorySize()); 664 665 mMotionEvent2.setAction(MotionEvent.ACTION_MOVE); 666 mMotionEvent2.addBatch(eventTime, x, y, pressure, size, 0); 667 assertEquals(1, mMotionEvent2.getHistorySize()); 668 } 669 670 @Test testRecycle()671 public void testRecycle() { 672 mMotionEvent2.setAction(MotionEvent.ACTION_MOVE); 673 assertEquals(0, mMotionEvent2.getHistorySize()); 674 mMotionEvent2.addBatch(mEventTime, 10.0f, 5.0f, 1.0f, 0.0f, 0); 675 assertEquals(1, mMotionEvent2.getHistorySize()); 676 677 mMotionEvent2.recycle(); 678 679 try { 680 mMotionEvent2.recycle(); 681 fail("recycle() should throw an exception when the event has already been recycled."); 682 } catch (RuntimeException ex) { 683 } 684 685 mMotionEvent2 = null; // since it was recycled, don't try to recycle again in tear down 686 } 687 688 @Test(expected=IllegalArgumentException.class) testTransformShouldThrowWhenMatrixIsNull()689 public void testTransformShouldThrowWhenMatrixIsNull() { 690 // transform() should throw an exception when matrix is null 691 mMotionEvent1.transform(null); 692 } 693 694 @Test testTransformShouldApplyMatrixToPointsAndPreserveRawPosition()695 public void testTransformShouldApplyMatrixToPointsAndPreserveRawPosition() { 696 // Generate some points on a circle, then assign each point to a pointer. 697 // The location of pointer 'i' is a point on a circle of radius ROTATION centered at (3,2) 698 // at an angle of ARC * i degrees clockwise relative to the Y axis. 699 // The geometrical representation is irrelevant to the test, it's just easy to generate 700 // and check rotation. We set the orientation to the same angle. 701 // Coordinate system: down is increasing Y, right is increasing X. 702 final float PI_180 = (float) (Math.PI / 180); 703 final float RADIUS = 10; 704 final float ARC = 36; 705 final float ROTATION = ARC * 2; 706 707 final int pointerCount = 11; 708 final int[] pointerIds = new int[pointerCount]; 709 final PointerCoords[] pointerCoords = new PointerCoords[pointerCount]; 710 final PointerCoords[] originalRawCoords = new PointerCoords[pointerCount]; 711 for (int i = 0; i < pointerCount; i++) { 712 final PointerCoords c = new PointerCoords(); 713 final float angle = (float) (i * ARC * PI_180); 714 pointerIds[i] = i; 715 pointerCoords[i] = c; 716 c.x = (float) (Math.sin(angle) * RADIUS + 3); 717 c.y = (float) (- Math.cos(angle) * RADIUS + 2); 718 c.orientation = angle; 719 originalRawCoords[i] = new PointerCoords(c); 720 } 721 final MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 722 pointerCount, pointerIds, pointerCoords, 0, 0, 0, 0, 0, 723 InputDevice.SOURCE_TOUCHSCREEN, 0); 724 dump("Original points.", event); 725 726 // Check original raw X and Y assumption. 727 for (int i = 0; i < pointerCount; i++) { 728 assertEquals(originalRawCoords[i].x, event.getRawX(i), RAW_COORD_TOLERANCE); 729 assertEquals(originalRawCoords[i].y, event.getRawY(i), RAW_COORD_TOLERANCE); 730 } 731 732 // Now translate the motion event so the circle's origin is at (0,0). 733 event.offsetLocation(-3, -2); 734 dump("Translated points.", event); 735 736 // Offsetting the location should preserve the raw X and Y of all pointers. 737 for (int i = 0; i < pointerCount; i++) { 738 assertEquals(originalRawCoords[i].x, event.getRawX(i), RAW_COORD_TOLERANCE); 739 assertEquals(originalRawCoords[i].y, event.getRawY(i), RAW_COORD_TOLERANCE); 740 } 741 742 // Apply a rotation about the origin by ROTATION degrees clockwise. 743 Matrix matrix = new Matrix(); 744 matrix.setRotate(ROTATION); 745 event.transform(matrix); 746 dump("Rotated points.", event); 747 748 // Check the points. 749 for (int i = 0; i < pointerCount; i++) { 750 final PointerCoords c = pointerCoords[i]; 751 event.getPointerCoords(i, c); 752 753 final float angle = (float) ((i * ARC + ROTATION) * PI_180); 754 assertEquals(Math.sin(angle) * RADIUS, c.x, RAW_COORD_TOLERANCE); 755 assertEquals(-Math.cos(angle) * RADIUS, c.y, RAW_COORD_TOLERANCE); 756 assertEquals(Math.tan(angle), Math.tan(c.orientation), 0.1); 757 758 // Applying the transformation should preserve the raw X and Y of all pointers. 759 assertEquals(originalRawCoords[i].x, event.getRawX(i), RAW_COORD_TOLERANCE); 760 assertEquals(originalRawCoords[i].y, event.getRawY(i), RAW_COORD_TOLERANCE); 761 } 762 } 763 dump(String label, MotionEvent ev)764 private void dump(String label, MotionEvent ev) { 765 if (false) { 766 StringBuilder msg = new StringBuilder(); 767 msg.append(label).append("\n"); 768 769 msg.append(" Raw: (").append(ev.getRawX()).append(",").append(ev.getRawY()).append(")\n"); 770 int pointerCount = ev.getPointerCount(); 771 for (int i = 0; i < pointerCount; i++) { 772 msg.append(" Pointer[").append(i).append("]: (") 773 .append(ev.getX(i)).append(",").append(ev.getY(i)).append("), orientation=") 774 .append(ev.getOrientation(i) * 180 / Math.PI).append(" deg\n"); 775 } 776 777 android.util.Log.i("TEST", msg.toString()); 778 } 779 } 780 781 @Test testPointerCoordsDefaultConstructor()782 public void testPointerCoordsDefaultConstructor() { 783 PointerCoords coords = new PointerCoords(); 784 785 assertEquals(0f, coords.x, 0.0f); 786 assertEquals(0f, coords.y, 0.0f); 787 assertEquals(0f, coords.pressure, 0.0f); 788 assertEquals(0f, coords.size, 0.0f); 789 assertEquals(0f, coords.touchMajor, 0.0f); 790 assertEquals(0f, coords.touchMinor, 0.0f); 791 assertEquals(0f, coords.toolMajor, 0.0f); 792 assertEquals(0f, coords.toolMinor, 0.0f); 793 assertEquals(0f, coords.orientation, 0.0f); 794 } 795 796 @Test testPointerCoordsCopyConstructor()797 public void testPointerCoordsCopyConstructor() { 798 PointerCoords coords = new PointerCoords(); 799 coords.x = 1; 800 coords.y = 2; 801 coords.pressure = 3; 802 coords.size = 4; 803 coords.touchMajor = 5; 804 coords.touchMinor = 6; 805 coords.toolMajor = 7; 806 coords.toolMinor = 8; 807 coords.orientation = 9; 808 coords.setAxisValue(MotionEvent.AXIS_GENERIC_1, 10); 809 810 PointerCoords copy = new PointerCoords(coords); 811 assertEquals(1f, copy.x, 0.0f); 812 assertEquals(2f, copy.y, 0.0f); 813 assertEquals(3f, copy.pressure, 0.0f); 814 assertEquals(4f, copy.size, 0.0f); 815 assertEquals(5f, copy.touchMajor, 0.0f); 816 assertEquals(6f, copy.touchMinor, 0.0f); 817 assertEquals(7f, copy.toolMajor, 0.0f); 818 assertEquals(8f, copy.toolMinor, 0.0f); 819 assertEquals(9f, copy.orientation, 0.0f); 820 assertEquals(10f, coords.getAxisValue(MotionEvent.AXIS_GENERIC_1), 0.0f); 821 } 822 823 @Test testPointerCoordsCopyFrom()824 public void testPointerCoordsCopyFrom() { 825 PointerCoords coords = new PointerCoords(); 826 coords.x = 1; 827 coords.y = 2; 828 coords.pressure = 3; 829 coords.size = 4; 830 coords.touchMajor = 5; 831 coords.touchMinor = 6; 832 coords.toolMajor = 7; 833 coords.toolMinor = 8; 834 coords.orientation = 9; 835 coords.setAxisValue(MotionEvent.AXIS_GENERIC_1, 10); 836 837 PointerCoords copy = new PointerCoords(); 838 copy.copyFrom(coords); 839 assertEquals(1f, copy.x, 0.0f); 840 assertEquals(2f, copy.y, 0.0f); 841 assertEquals(3f, copy.pressure, 0.0f); 842 assertEquals(4f, copy.size, 0.0f); 843 assertEquals(5f, copy.touchMajor, 0.0f); 844 assertEquals(6f, copy.touchMinor, 0.0f); 845 assertEquals(7f, copy.toolMajor, 0.0f); 846 assertEquals(8f, copy.toolMinor, 0.0f); 847 assertEquals(9f, copy.orientation, 0.0f); 848 assertEquals(10f, coords.getAxisValue(MotionEvent.AXIS_GENERIC_1), 0.0f); 849 } 850 851 @Test testPointerPropertiesDefaultConstructor()852 public void testPointerPropertiesDefaultConstructor() { 853 PointerProperties properties = new PointerProperties(); 854 855 assertEquals(MotionEvent.INVALID_POINTER_ID, properties.id); 856 assertEquals(MotionEvent.TOOL_TYPE_UNKNOWN, properties.toolType); 857 } 858 859 @Test testPointerPropertiesCopyConstructor()860 public void testPointerPropertiesCopyConstructor() { 861 PointerProperties properties = new PointerProperties(); 862 properties.id = 1; 863 properties.toolType = MotionEvent.TOOL_TYPE_MOUSE; 864 865 PointerProperties copy = new PointerProperties(properties); 866 assertEquals(1, copy.id); 867 assertEquals(MotionEvent.TOOL_TYPE_MOUSE, copy.toolType); 868 } 869 870 @Test testPointerPropertiesCopyFrom()871 public void testPointerPropertiesCopyFrom() { 872 PointerProperties properties = new PointerProperties(); 873 properties.id = 1; 874 properties.toolType = MotionEvent.TOOL_TYPE_MOUSE; 875 876 PointerProperties copy = new PointerProperties(); 877 copy.copyFrom(properties); 878 assertEquals(1, copy.id); 879 assertEquals(MotionEvent.TOOL_TYPE_MOUSE, copy.toolType); 880 } 881 882 @Test testActionToString()883 public void testActionToString() { 884 final int[] actions = { 885 MotionEvent.ACTION_DOWN, 886 MotionEvent.ACTION_UP, 887 MotionEvent.ACTION_MOVE, 888 MotionEvent.ACTION_CANCEL, 889 MotionEvent.ACTION_OUTSIDE, 890 MotionEvent.ACTION_HOVER_MOVE, 891 MotionEvent.ACTION_SCROLL, 892 MotionEvent.ACTION_HOVER_ENTER, 893 MotionEvent.ACTION_HOVER_EXIT, 894 MotionEvent.ACTION_BUTTON_PRESS, 895 MotionEvent.ACTION_BUTTON_RELEASE 896 }; 897 898 // There is no hard guarantee on the actual return result on any specific action 899 // from MotionEvent.actionToString. Verify that we are not crashing on those calls 900 // and that the return result on each is not empty 901 for (int i = 0; i < actions.length; i++) { 902 assertFalse(TextUtils.isEmpty(MotionEvent.actionToString(actions[i]))); 903 } 904 905 final int[] pointerActions = { 906 MotionEvent.ACTION_POINTER_UP, 907 MotionEvent.ACTION_POINTER_DOWN 908 }; 909 910 for (int i = 0; i < pointerActions.length; i++) { 911 for (int pointer = 0; pointer < 5; pointer++) { 912 int pointerAction = 913 pointerActions[i] | pointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT; 914 assertFalse(TextUtils.isEmpty(MotionEvent.actionToString(pointerAction))); 915 } 916 } 917 } 918 919 @Test testAxisFromToString()920 public void testAxisFromToString() { 921 final int[] axes = { 922 MotionEvent.AXIS_X, 923 MotionEvent.AXIS_Y, 924 MotionEvent.AXIS_PRESSURE, 925 MotionEvent.AXIS_SIZE, 926 MotionEvent.AXIS_TOUCH_MAJOR, 927 MotionEvent.AXIS_TOUCH_MINOR, 928 MotionEvent.AXIS_TOOL_MAJOR, 929 MotionEvent.AXIS_TOOL_MINOR, 930 MotionEvent.AXIS_ORIENTATION, 931 MotionEvent.AXIS_VSCROLL, 932 MotionEvent.AXIS_HSCROLL, 933 MotionEvent.AXIS_Z, 934 MotionEvent.AXIS_RX, 935 MotionEvent.AXIS_RY, 936 MotionEvent.AXIS_RZ, 937 MotionEvent.AXIS_HAT_X, 938 MotionEvent.AXIS_HAT_Y, 939 MotionEvent.AXIS_LTRIGGER, 940 MotionEvent.AXIS_RTRIGGER, 941 MotionEvent.AXIS_THROTTLE, 942 MotionEvent.AXIS_RUDDER, 943 MotionEvent.AXIS_WHEEL, 944 MotionEvent.AXIS_GAS, 945 MotionEvent.AXIS_BRAKE, 946 MotionEvent.AXIS_DISTANCE, 947 MotionEvent.AXIS_TILT, 948 MotionEvent.AXIS_SCROLL, 949 MotionEvent.AXIS_RELATIVE_X, 950 MotionEvent.AXIS_RELATIVE_Y, 951 MotionEvent.AXIS_GENERIC_1, 952 MotionEvent.AXIS_GENERIC_2, 953 MotionEvent.AXIS_GENERIC_3, 954 MotionEvent.AXIS_GENERIC_4, 955 MotionEvent.AXIS_GENERIC_5, 956 MotionEvent.AXIS_GENERIC_6, 957 MotionEvent.AXIS_GENERIC_7, 958 MotionEvent.AXIS_GENERIC_8, 959 MotionEvent.AXIS_GENERIC_9, 960 MotionEvent.AXIS_GENERIC_10, 961 MotionEvent.AXIS_GENERIC_11, 962 MotionEvent.AXIS_GENERIC_12, 963 MotionEvent.AXIS_GENERIC_13, 964 MotionEvent.AXIS_GENERIC_14, 965 MotionEvent.AXIS_GENERIC_15, 966 MotionEvent.AXIS_GENERIC_16, 967 MotionEvent.AXIS_GESTURE_X_OFFSET, 968 MotionEvent.AXIS_GESTURE_Y_OFFSET, 969 MotionEvent.AXIS_GESTURE_SCROLL_X_DISTANCE, 970 MotionEvent.AXIS_GESTURE_SCROLL_Y_DISTANCE, 971 MotionEvent.AXIS_GESTURE_PINCH_SCALE_FACTOR, 972 }; 973 974 // There is no hard guarantee on the actual return result on any specific axis 975 // from MotionEvent.axisToString. Verify that we are not crashing on those calls 976 // and that the return result on each is not empty. However, we do expect the two-way 977 // call chain of to/from to get us back to the original integer value. 978 for (int i = 0; i < axes.length; i++) { 979 String axisToString = MotionEvent.axisToString(axes[i]); 980 assertFalse(TextUtils.isEmpty(axisToString)); 981 assertEquals(axes[i], MotionEvent.axisFromString(axisToString)); 982 } 983 } 984 985 @Test testGetActionButton()986 public void testGetActionButton() { 987 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 988 MotionEvent.ACTION_BUTTON_PRESS, X_3F, Y_4F, 0); 989 mMotionEventDynamic.setActionButton(MotionEvent.BUTTON_STYLUS_PRIMARY); 990 assertEquals(MotionEvent.BUTTON_STYLUS_PRIMARY, mMotionEventDynamic.getActionButton()); 991 mMotionEventDynamic.recycle(); 992 993 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 994 MotionEvent.ACTION_BUTTON_PRESS, X_3F, Y_4F, 0); 995 mMotionEventDynamic.setActionButton(MotionEvent.BUTTON_SECONDARY); 996 assertEquals(MotionEvent.BUTTON_SECONDARY, mMotionEventDynamic.getActionButton()); 997 } 998 999 @Test testIsButtonPressed()1000 public void testIsButtonPressed() { 1001 mMotionEventDynamic = MotionEvent.obtain(mDownTime, mEventTime, 1002 MotionEvent.ACTION_DOWN, X_3F, Y_4F, 0); 1003 mMotionEventDynamic.setSource(InputDevice.SOURCE_MOUSE); 1004 1005 mMotionEventDynamic.setButtonState( 1006 MotionEvent.BUTTON_PRIMARY | MotionEvent.BUTTON_STYLUS_PRIMARY); 1007 assertTrue(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_PRIMARY)); 1008 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_SECONDARY)); 1009 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_TERTIARY)); 1010 assertTrue(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY)); 1011 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY)); 1012 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_BACK)); 1013 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_FORWARD)); 1014 1015 mMotionEventDynamic.setButtonState(MotionEvent.BUTTON_PRIMARY); 1016 assertTrue(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_PRIMARY)); 1017 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_SECONDARY)); 1018 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_TERTIARY)); 1019 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY)); 1020 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY)); 1021 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_BACK)); 1022 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_FORWARD)); 1023 1024 mMotionEventDynamic.setButtonState( 1025 MotionEvent.BUTTON_FORWARD | MotionEvent.BUTTON_TERTIARY); 1026 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_PRIMARY)); 1027 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_SECONDARY)); 1028 assertTrue(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_TERTIARY)); 1029 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY)); 1030 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY)); 1031 assertFalse(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_BACK)); 1032 assertTrue(mMotionEventDynamic.isButtonPressed(MotionEvent.BUTTON_FORWARD)); 1033 } 1034 1035 @Test testClassificationConstantsAreUnique()1036 public void testClassificationConstantsAreUnique() { 1037 Set<Integer> values = new LinkedHashSet<>(); 1038 values.add(MotionEvent.CLASSIFICATION_NONE); 1039 values.add(MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE); 1040 values.add(MotionEvent.CLASSIFICATION_DEEP_PRESS); 1041 assertEquals(3, values.size()); 1042 } 1043 1044 /** 1045 * The motion events 1 and 2 were created using one of the obtain methods. 1046 * As a result, they should not have any classification. 1047 * Only events generated by the framework are allowed to have classification other than NONE. 1048 */ 1049 @Test testGetClassification()1050 public void testGetClassification() { 1051 assertEquals(MotionEvent.CLASSIFICATION_NONE, mMotionEvent1.getClassification()); 1052 assertEquals(MotionEvent.CLASSIFICATION_NONE, mMotionEvent2.getClassification()); 1053 } 1054 1055 @Test testNativeConverter()1056 public void testNativeConverter() { 1057 final MotionEvent event = MotionEvent.obtain(mDownTime, mEventTime, 1058 MotionEvent.ACTION_BUTTON_PRESS, X_3F, Y_4F, META_STATE); 1059 event.setActionButton(MotionEvent.BUTTON_PRIMARY); 1060 nativeMotionEventTest(event); 1061 } 1062 } 1063