1/*
2 * Copyright (C) 2011 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#include <math.h>
18
19#include <binder/Parcel.h>
20#include <gtest/gtest.h>
21#include <input/Input.h>
22
23namespace android {
24
25class BaseTest : public testing::Test {
26protected:
27    virtual void SetUp() { }
28    virtual void TearDown() { }
29};
30
31// --- PointerCoordsTest ---
32
33class PointerCoordsTest : public BaseTest {
34};
35
36TEST_F(PointerCoordsTest, ClearSetsBitsToZero) {
37    PointerCoords coords;
38    coords.clear();
39
40    ASSERT_EQ(0ULL, coords.bits);
41}
42
43TEST_F(PointerCoordsTest, AxisValues) {
44    float* valuePtr;
45    PointerCoords coords;
46    coords.clear();
47
48    // Check invariants when no axes are present.
49    ASSERT_EQ(0, coords.getAxisValue(0))
50            << "getAxisValue should return zero because axis is not present";
51    ASSERT_EQ(0, coords.getAxisValue(1))
52            << "getAxisValue should return zero because axis is not present";
53
54    // Set first axis.
55    ASSERT_EQ(OK, coords.setAxisValue(1, 5));
56    ASSERT_EQ(5, coords.values[0]);
57    ASSERT_EQ(0x4000000000000000ULL, coords.bits);
58
59    ASSERT_EQ(0, coords.getAxisValue(0))
60            << "getAxisValue should return zero because axis is not present";
61    ASSERT_EQ(5, coords.getAxisValue(1))
62            << "getAxisValue should return value of axis";
63
64    // Set an axis with a higher id than all others.  (appending value at the end)
65    ASSERT_EQ(OK, coords.setAxisValue(3, 2));
66    ASSERT_EQ(0x5000000000000000ULL, coords.bits);
67    ASSERT_EQ(5, coords.values[0]);
68    ASSERT_EQ(2, coords.values[1]);
69
70    ASSERT_EQ(0, coords.getAxisValue(0))
71            << "getAxisValue should return zero because axis is not present";
72    ASSERT_EQ(5, coords.getAxisValue(1))
73            << "getAxisValue should return value of axis";
74    ASSERT_EQ(0, coords.getAxisValue(2))
75            << "getAxisValue should return zero because axis is not present";
76    ASSERT_EQ(2, coords.getAxisValue(3))
77            << "getAxisValue should return value of axis";
78
79    // Set an axis with an id lower than all others.  (prepending value at beginning)
80    ASSERT_EQ(OK, coords.setAxisValue(0, 4));
81    ASSERT_EQ(0xd000000000000000ULL, coords.bits);
82    ASSERT_EQ(4, coords.values[0]);
83    ASSERT_EQ(5, coords.values[1]);
84    ASSERT_EQ(2, coords.values[2]);
85
86    ASSERT_EQ(4, coords.getAxisValue(0))
87            << "getAxisValue should return value of axis";
88    ASSERT_EQ(5, coords.getAxisValue(1))
89            << "getAxisValue should return value of axis";
90    ASSERT_EQ(0, coords.getAxisValue(2))
91            << "getAxisValue should return zero because axis is not present";
92    ASSERT_EQ(2, coords.getAxisValue(3))
93            << "getAxisValue should return value of axis";
94
95    // Set an axis with an id between the others.  (inserting value in the middle)
96    ASSERT_EQ(OK, coords.setAxisValue(2, 1));
97    ASSERT_EQ(0xf000000000000000ULL, coords.bits);
98    ASSERT_EQ(4, coords.values[0]);
99    ASSERT_EQ(5, coords.values[1]);
100    ASSERT_EQ(1, coords.values[2]);
101    ASSERT_EQ(2, coords.values[3]);
102
103    ASSERT_EQ(4, coords.getAxisValue(0))
104            << "getAxisValue should return value of axis";
105    ASSERT_EQ(5, coords.getAxisValue(1))
106            << "getAxisValue should return value of axis";
107    ASSERT_EQ(1, coords.getAxisValue(2))
108            << "getAxisValue should return value of axis";
109    ASSERT_EQ(2, coords.getAxisValue(3))
110            << "getAxisValue should return value of axis";
111
112    // Set an existing axis value in place.
113    ASSERT_EQ(OK, coords.setAxisValue(1, 6));
114    ASSERT_EQ(0xf000000000000000ULL, coords.bits);
115    ASSERT_EQ(4, coords.values[0]);
116    ASSERT_EQ(6, coords.values[1]);
117    ASSERT_EQ(1, coords.values[2]);
118    ASSERT_EQ(2, coords.values[3]);
119
120    ASSERT_EQ(4, coords.getAxisValue(0))
121            << "getAxisValue should return value of axis";
122    ASSERT_EQ(6, coords.getAxisValue(1))
123            << "getAxisValue should return value of axis";
124    ASSERT_EQ(1, coords.getAxisValue(2))
125            << "getAxisValue should return value of axis";
126    ASSERT_EQ(2, coords.getAxisValue(3))
127            << "getAxisValue should return value of axis";
128
129    // Set maximum number of axes.
130    for (size_t axis = 4; axis < PointerCoords::MAX_AXES; axis++) {
131        ASSERT_EQ(OK, coords.setAxisValue(axis, axis));
132    }
133    ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcountll(coords.bits));
134
135    // Try to set one more axis beyond maximum number.
136    // Ensure bits are unchanged.
137    ASSERT_EQ(NO_MEMORY, coords.setAxisValue(PointerCoords::MAX_AXES, 100));
138    ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcountll(coords.bits));
139}
140
141TEST_F(PointerCoordsTest, Parcel) {
142    Parcel parcel;
143
144    PointerCoords inCoords;
145    inCoords.clear();
146    PointerCoords outCoords;
147
148    // Round trip with empty coords.
149    inCoords.writeToParcel(&parcel);
150    parcel.setDataPosition(0);
151    outCoords.readFromParcel(&parcel);
152
153    ASSERT_EQ(0ULL, outCoords.bits);
154
155    // Round trip with some values.
156    parcel.freeData();
157    inCoords.setAxisValue(2, 5);
158    inCoords.setAxisValue(5, 8);
159
160    inCoords.writeToParcel(&parcel);
161    parcel.setDataPosition(0);
162    outCoords.readFromParcel(&parcel);
163
164    ASSERT_EQ(outCoords.bits, inCoords.bits);
165    ASSERT_EQ(outCoords.values[0], inCoords.values[0]);
166    ASSERT_EQ(outCoords.values[1], inCoords.values[1]);
167}
168
169
170// --- KeyEventTest ---
171
172class KeyEventTest : public BaseTest {
173};
174
175TEST_F(KeyEventTest, Properties) {
176    KeyEvent event;
177
178    // Initialize and get properties.
179    const nsecs_t ARBITRARY_DOWN_TIME = 1;
180    const nsecs_t ARBITRARY_EVENT_TIME = 2;
181    event.initialize(2, AINPUT_SOURCE_GAMEPAD, AKEY_EVENT_ACTION_DOWN,
182            AKEY_EVENT_FLAG_FROM_SYSTEM, AKEYCODE_BUTTON_X, 121,
183            AMETA_ALT_ON, 1, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME);
184
185    ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType());
186    ASSERT_EQ(2, event.getDeviceId());
187    ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_GAMEPAD), event.getSource());
188    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction());
189    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, event.getFlags());
190    ASSERT_EQ(AKEYCODE_BUTTON_X, event.getKeyCode());
191    ASSERT_EQ(121, event.getScanCode());
192    ASSERT_EQ(AMETA_ALT_ON, event.getMetaState());
193    ASSERT_EQ(1, event.getRepeatCount());
194    ASSERT_EQ(ARBITRARY_DOWN_TIME, event.getDownTime());
195    ASSERT_EQ(ARBITRARY_EVENT_TIME, event.getEventTime());
196
197    // Set source.
198    event.setSource(AINPUT_SOURCE_JOYSTICK);
199    ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
200}
201
202
203// --- MotionEventTest ---
204
205class MotionEventTest : public BaseTest {
206protected:
207    static const nsecs_t ARBITRARY_DOWN_TIME;
208    static const nsecs_t ARBITRARY_EVENT_TIME;
209    static const float X_OFFSET;
210    static const float Y_OFFSET;
211
212    void initializeEventWithHistory(MotionEvent* event);
213    void assertEqualsEventWithHistory(const MotionEvent* event);
214};
215
216const nsecs_t MotionEventTest::ARBITRARY_DOWN_TIME = 1;
217const nsecs_t MotionEventTest::ARBITRARY_EVENT_TIME = 2;
218const float MotionEventTest::X_OFFSET = 1.0f;
219const float MotionEventTest::Y_OFFSET = 1.1f;
220
221void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
222    PointerProperties pointerProperties[2];
223    pointerProperties[0].clear();
224    pointerProperties[0].id = 1;
225    pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
226    pointerProperties[1].clear();
227    pointerProperties[1].id = 2;
228    pointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
229
230    PointerCoords pointerCoords[2];
231    pointerCoords[0].clear();
232    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 10);
233    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 11);
234    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 12);
235    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 13);
236    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 14);
237    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 15);
238    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 16);
239    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 17);
240    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 18);
241    pointerCoords[1].clear();
242    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 20);
243    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 21);
244    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22);
245    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 23);
246    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 24);
247    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 25);
248    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26);
249    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
250    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
251    event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE, 0,
252            AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
253            AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
254            X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
255            ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
256            2, pointerProperties, pointerCoords);
257
258    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
259    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
260    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 112);
261    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 113);
262    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 114);
263    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 115);
264    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 116);
265    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 117);
266    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 118);
267    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 120);
268    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 121);
269    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 122);
270    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 123);
271    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 124);
272    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 125);
273    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 126);
274    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 127);
275    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 128);
276    event->addSample(ARBITRARY_EVENT_TIME + 1, pointerCoords);
277
278    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 210);
279    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 211);
280    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 212);
281    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 213);
282    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 214);
283    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 215);
284    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 216);
285    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 217);
286    pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 218);
287    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 220);
288    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 221);
289    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 222);
290    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 223);
291    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 224);
292    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 225);
293    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 226);
294    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 227);
295    pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 228);
296    event->addSample(ARBITRARY_EVENT_TIME + 2, pointerCoords);
297}
298
299void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
300    // Check properties.
301    ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
302    ASSERT_EQ(2, event->getDeviceId());
303    ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_TOUCHSCREEN), event->getSource());
304    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction());
305    ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
306    ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
307    ASSERT_EQ(AMETA_ALT_ON, event->getMetaState());
308    ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState());
309    ASSERT_EQ(X_OFFSET, event->getXOffset());
310    ASSERT_EQ(Y_OFFSET, event->getYOffset());
311    ASSERT_EQ(2.0f, event->getXPrecision());
312    ASSERT_EQ(2.1f, event->getYPrecision());
313    ASSERT_EQ(ARBITRARY_DOWN_TIME, event->getDownTime());
314
315    ASSERT_EQ(2U, event->getPointerCount());
316    ASSERT_EQ(1, event->getPointerId(0));
317    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, event->getToolType(0));
318    ASSERT_EQ(2, event->getPointerId(1));
319    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, event->getToolType(1));
320
321    ASSERT_EQ(2U, event->getHistorySize());
322
323    // Check data.
324    ASSERT_EQ(ARBITRARY_EVENT_TIME, event->getHistoricalEventTime(0));
325    ASSERT_EQ(ARBITRARY_EVENT_TIME + 1, event->getHistoricalEventTime(1));
326    ASSERT_EQ(ARBITRARY_EVENT_TIME + 2, event->getEventTime());
327
328    ASSERT_EQ(11, event->getHistoricalRawPointerCoords(0, 0)->
329            getAxisValue(AMOTION_EVENT_AXIS_Y));
330    ASSERT_EQ(21, event->getHistoricalRawPointerCoords(1, 0)->
331            getAxisValue(AMOTION_EVENT_AXIS_Y));
332    ASSERT_EQ(111, event->getHistoricalRawPointerCoords(0, 1)->
333            getAxisValue(AMOTION_EVENT_AXIS_Y));
334    ASSERT_EQ(121, event->getHistoricalRawPointerCoords(1, 1)->
335            getAxisValue(AMOTION_EVENT_AXIS_Y));
336    ASSERT_EQ(211, event->getRawPointerCoords(0)->
337            getAxisValue(AMOTION_EVENT_AXIS_Y));
338    ASSERT_EQ(221, event->getRawPointerCoords(1)->
339            getAxisValue(AMOTION_EVENT_AXIS_Y));
340
341    ASSERT_EQ(11, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0));
342    ASSERT_EQ(21, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0));
343    ASSERT_EQ(111, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1));
344    ASSERT_EQ(121, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1));
345    ASSERT_EQ(211, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0));
346    ASSERT_EQ(221, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1));
347
348    ASSERT_EQ(10, event->getHistoricalRawX(0, 0));
349    ASSERT_EQ(20, event->getHistoricalRawX(1, 0));
350    ASSERT_EQ(110, event->getHistoricalRawX(0, 1));
351    ASSERT_EQ(120, event->getHistoricalRawX(1, 1));
352    ASSERT_EQ(210, event->getRawX(0));
353    ASSERT_EQ(220, event->getRawX(1));
354
355    ASSERT_EQ(11, event->getHistoricalRawY(0, 0));
356    ASSERT_EQ(21, event->getHistoricalRawY(1, 0));
357    ASSERT_EQ(111, event->getHistoricalRawY(0, 1));
358    ASSERT_EQ(121, event->getHistoricalRawY(1, 1));
359    ASSERT_EQ(211, event->getRawY(0));
360    ASSERT_EQ(221, event->getRawY(1));
361
362    ASSERT_EQ(X_OFFSET + 10, event->getHistoricalX(0, 0));
363    ASSERT_EQ(X_OFFSET + 20, event->getHistoricalX(1, 0));
364    ASSERT_EQ(X_OFFSET + 110, event->getHistoricalX(0, 1));
365    ASSERT_EQ(X_OFFSET + 120, event->getHistoricalX(1, 1));
366    ASSERT_EQ(X_OFFSET + 210, event->getX(0));
367    ASSERT_EQ(X_OFFSET + 220, event->getX(1));
368
369    ASSERT_EQ(Y_OFFSET + 11, event->getHistoricalY(0, 0));
370    ASSERT_EQ(Y_OFFSET + 21, event->getHistoricalY(1, 0));
371    ASSERT_EQ(Y_OFFSET + 111, event->getHistoricalY(0, 1));
372    ASSERT_EQ(Y_OFFSET + 121, event->getHistoricalY(1, 1));
373    ASSERT_EQ(Y_OFFSET + 211, event->getY(0));
374    ASSERT_EQ(Y_OFFSET + 221, event->getY(1));
375
376    ASSERT_EQ(12, event->getHistoricalPressure(0, 0));
377    ASSERT_EQ(22, event->getHistoricalPressure(1, 0));
378    ASSERT_EQ(112, event->getHistoricalPressure(0, 1));
379    ASSERT_EQ(122, event->getHistoricalPressure(1, 1));
380    ASSERT_EQ(212, event->getPressure(0));
381    ASSERT_EQ(222, event->getPressure(1));
382
383    ASSERT_EQ(13, event->getHistoricalSize(0, 0));
384    ASSERT_EQ(23, event->getHistoricalSize(1, 0));
385    ASSERT_EQ(113, event->getHistoricalSize(0, 1));
386    ASSERT_EQ(123, event->getHistoricalSize(1, 1));
387    ASSERT_EQ(213, event->getSize(0));
388    ASSERT_EQ(223, event->getSize(1));
389
390    ASSERT_EQ(14, event->getHistoricalTouchMajor(0, 0));
391    ASSERT_EQ(24, event->getHistoricalTouchMajor(1, 0));
392    ASSERT_EQ(114, event->getHistoricalTouchMajor(0, 1));
393    ASSERT_EQ(124, event->getHistoricalTouchMajor(1, 1));
394    ASSERT_EQ(214, event->getTouchMajor(0));
395    ASSERT_EQ(224, event->getTouchMajor(1));
396
397    ASSERT_EQ(15, event->getHistoricalTouchMinor(0, 0));
398    ASSERT_EQ(25, event->getHistoricalTouchMinor(1, 0));
399    ASSERT_EQ(115, event->getHistoricalTouchMinor(0, 1));
400    ASSERT_EQ(125, event->getHistoricalTouchMinor(1, 1));
401    ASSERT_EQ(215, event->getTouchMinor(0));
402    ASSERT_EQ(225, event->getTouchMinor(1));
403
404    ASSERT_EQ(16, event->getHistoricalToolMajor(0, 0));
405    ASSERT_EQ(26, event->getHistoricalToolMajor(1, 0));
406    ASSERT_EQ(116, event->getHistoricalToolMajor(0, 1));
407    ASSERT_EQ(126, event->getHistoricalToolMajor(1, 1));
408    ASSERT_EQ(216, event->getToolMajor(0));
409    ASSERT_EQ(226, event->getToolMajor(1));
410
411    ASSERT_EQ(17, event->getHistoricalToolMinor(0, 0));
412    ASSERT_EQ(27, event->getHistoricalToolMinor(1, 0));
413    ASSERT_EQ(117, event->getHistoricalToolMinor(0, 1));
414    ASSERT_EQ(127, event->getHistoricalToolMinor(1, 1));
415    ASSERT_EQ(217, event->getToolMinor(0));
416    ASSERT_EQ(227, event->getToolMinor(1));
417
418    ASSERT_EQ(18, event->getHistoricalOrientation(0, 0));
419    ASSERT_EQ(28, event->getHistoricalOrientation(1, 0));
420    ASSERT_EQ(118, event->getHistoricalOrientation(0, 1));
421    ASSERT_EQ(128, event->getHistoricalOrientation(1, 1));
422    ASSERT_EQ(218, event->getOrientation(0));
423    ASSERT_EQ(228, event->getOrientation(1));
424}
425
426TEST_F(MotionEventTest, Properties) {
427    MotionEvent event;
428
429    // Initialize, add samples and check properties.
430    initializeEventWithHistory(&event);
431    ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&event));
432
433    // Set source.
434    event.setSource(AINPUT_SOURCE_JOYSTICK);
435    ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
436
437    // Set action.
438    event.setAction(AMOTION_EVENT_ACTION_CANCEL);
439    ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
440
441    // Set meta state.
442    event.setMetaState(AMETA_CTRL_ON);
443    ASSERT_EQ(AMETA_CTRL_ON, event.getMetaState());
444}
445
446TEST_F(MotionEventTest, CopyFrom_KeepHistory) {
447    MotionEvent event;
448    initializeEventWithHistory(&event);
449
450    MotionEvent copy;
451    copy.copyFrom(&event, true /*keepHistory*/);
452
453    ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&event));
454}
455
456TEST_F(MotionEventTest, CopyFrom_DoNotKeepHistory) {
457    MotionEvent event;
458    initializeEventWithHistory(&event);
459
460    MotionEvent copy;
461    copy.copyFrom(&event, false /*keepHistory*/);
462
463    ASSERT_EQ(event.getPointerCount(), copy.getPointerCount());
464    ASSERT_EQ(0U, copy.getHistorySize());
465
466    ASSERT_EQ(event.getPointerId(0), copy.getPointerId(0));
467    ASSERT_EQ(event.getPointerId(1), copy.getPointerId(1));
468
469    ASSERT_EQ(event.getEventTime(), copy.getEventTime());
470
471    ASSERT_EQ(event.getX(0), copy.getX(0));
472}
473
474TEST_F(MotionEventTest, OffsetLocation) {
475    MotionEvent event;
476    initializeEventWithHistory(&event);
477
478    event.offsetLocation(5.0f, -2.0f);
479
480    ASSERT_EQ(X_OFFSET + 5.0f, event.getXOffset());
481    ASSERT_EQ(Y_OFFSET - 2.0f, event.getYOffset());
482}
483
484TEST_F(MotionEventTest, Scale) {
485    MotionEvent event;
486    initializeEventWithHistory(&event);
487
488    event.scale(2.0f);
489
490    ASSERT_EQ(X_OFFSET * 2, event.getXOffset());
491    ASSERT_EQ(Y_OFFSET * 2, event.getYOffset());
492
493    ASSERT_EQ(210 * 2, event.getRawX(0));
494    ASSERT_EQ(211 * 2, event.getRawY(0));
495    ASSERT_EQ((X_OFFSET + 210) * 2, event.getX(0));
496    ASSERT_EQ((Y_OFFSET + 211) * 2, event.getY(0));
497    ASSERT_EQ(212, event.getPressure(0));
498    ASSERT_EQ(213, event.getSize(0));
499    ASSERT_EQ(214 * 2, event.getTouchMajor(0));
500    ASSERT_EQ(215 * 2, event.getTouchMinor(0));
501    ASSERT_EQ(216 * 2, event.getToolMajor(0));
502    ASSERT_EQ(217 * 2, event.getToolMinor(0));
503    ASSERT_EQ(218, event.getOrientation(0));
504}
505
506TEST_F(MotionEventTest, Parcel) {
507    Parcel parcel;
508
509    MotionEvent inEvent;
510    initializeEventWithHistory(&inEvent);
511    MotionEvent outEvent;
512
513    // Round trip.
514    inEvent.writeToParcel(&parcel);
515    parcel.setDataPosition(0);
516    outEvent.readFromParcel(&parcel);
517
518    ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent));
519}
520
521static void setRotationMatrix(float matrix[9], float angle) {
522    float sin = sinf(angle);
523    float cos = cosf(angle);
524    matrix[0] = cos;
525    matrix[1] = -sin;
526    matrix[2] = 0;
527    matrix[3] = sin;
528    matrix[4] = cos;
529    matrix[5] = 0;
530    matrix[6] = 0;
531    matrix[7] = 0;
532    matrix[8] = 1.0f;
533}
534
535TEST_F(MotionEventTest, Transform) {
536    // Generate some points on a circle.
537    // Each point 'i' is a point on a circle of radius ROTATION centered at (3,2) at an angle
538    // of ARC * i degrees clockwise relative to the Y axis.
539    // The geometrical representation is irrelevant to the test, it's just easy to generate
540    // and check rotation.  We set the orientation to the same angle.
541    // Coordinate system: down is increasing Y, right is increasing X.
542    const float PI_180 = float(M_PI / 180);
543    const float RADIUS = 10;
544    const float ARC = 36;
545    const float ROTATION = ARC * 2;
546
547    const size_t pointerCount = 11;
548    PointerProperties pointerProperties[pointerCount];
549    PointerCoords pointerCoords[pointerCount];
550    for (size_t i = 0; i < pointerCount; i++) {
551        float angle = float(i * ARC * PI_180);
552        pointerProperties[i].clear();
553        pointerProperties[i].id = i;
554        pointerCoords[i].clear();
555        pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, sinf(angle) * RADIUS + 3);
556        pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, -cosf(angle) * RADIUS + 2);
557        pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
558    }
559    MotionEvent event;
560    event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0,
561            0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
562    float originalRawX = 0 + 3;
563    float originalRawY = -RADIUS + 2;
564
565    // Check original raw X and Y assumption.
566    ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
567    ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
568
569    // Now translate the motion event so the circle's origin is at (0,0).
570    event.offsetLocation(-3, -2);
571
572    // Offsetting the location should preserve the raw X and Y of the first point.
573    ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
574    ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
575
576    // Apply a rotation about the origin by ROTATION degrees clockwise.
577    float matrix[9];
578    setRotationMatrix(matrix, ROTATION * PI_180);
579    event.transform(matrix);
580
581    // Check the points.
582    for (size_t i = 0; i < pointerCount; i++) {
583        float angle = float((i * ARC + ROTATION) * PI_180);
584        ASSERT_NEAR(sinf(angle) * RADIUS, event.getX(i), 0.001);
585        ASSERT_NEAR(-cosf(angle) * RADIUS, event.getY(i), 0.001);
586        ASSERT_NEAR(tanf(angle), tanf(event.getOrientation(i)), 0.1);
587    }
588
589    // Applying the transformation should preserve the raw X and Y of the first point.
590    ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001);
591    ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
592}
593
594} // namespace android
595