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