1//
2// Copyright 2010 The Android Open Source Project
3//
4
5#include <ui/InputTransport.h>
6#include <utils/Timers.h>
7#include <utils/StopWatch.h>
8#include <gtest/gtest.h>
9#include <unistd.h>
10#include <time.h>
11#include <sys/mman.h>
12#include <cutils/ashmem.h>
13
14#include "../../utils/tests/TestHelpers.h"
15
16namespace android {
17
18class InputPublisherAndConsumerTest : public testing::Test {
19protected:
20    sp<InputChannel> serverChannel, clientChannel;
21    InputPublisher* mPublisher;
22    InputConsumer* mConsumer;
23    PreallocatedInputEventFactory mEventFactory;
24
25    virtual void SetUp() {
26        status_t result = InputChannel::openInputChannelPair(String8("channel name"),
27                serverChannel, clientChannel);
28
29        mPublisher = new InputPublisher(serverChannel);
30        mConsumer = new InputConsumer(clientChannel);
31    }
32
33    virtual void TearDown() {
34        if (mPublisher) {
35            delete mPublisher;
36            mPublisher = NULL;
37        }
38
39        if (mConsumer) {
40            delete mConsumer;
41            mConsumer = NULL;
42        }
43
44        serverChannel.clear();
45        clientChannel.clear();
46    }
47
48    void Initialize();
49    void PublishAndConsumeKeyEvent();
50    void PublishAndConsumeMotionEvent(
51            size_t samplesToAppendBeforeDispatch = 0,
52            size_t samplesToAppendAfterDispatch = 0);
53};
54
55TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) {
56    EXPECT_EQ(serverChannel.get(), mPublisher->getChannel().get());
57    EXPECT_EQ(clientChannel.get(), mConsumer->getChannel().get());
58}
59
60void InputPublisherAndConsumerTest::Initialize() {
61    status_t status;
62
63    status = mPublisher->initialize();
64    ASSERT_EQ(OK, status)
65            << "publisher initialize should return OK";
66
67    status = mConsumer->initialize();
68    ASSERT_EQ(OK, status)
69            << "consumer initialize should return OK";
70}
71
72void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() {
73    status_t status;
74
75    const int32_t deviceId = 1;
76    const int32_t source = AINPUT_SOURCE_KEYBOARD;
77    const int32_t action = AKEY_EVENT_ACTION_DOWN;
78    const int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
79    const int32_t keyCode = AKEYCODE_ENTER;
80    const int32_t scanCode = 13;
81    const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
82    const int32_t repeatCount = 1;
83    const nsecs_t downTime = 3;
84    const nsecs_t eventTime = 4;
85
86    status = mPublisher->publishKeyEvent(deviceId, source, action, flags,
87            keyCode, scanCode, metaState, repeatCount, downTime, eventTime);
88    ASSERT_EQ(OK, status)
89            << "publisher publishKeyEvent should return OK";
90
91    status = mPublisher->sendDispatchSignal();
92    ASSERT_EQ(OK, status)
93            << "publisher sendDispatchSignal should return OK";
94
95    status = mConsumer->receiveDispatchSignal();
96    ASSERT_EQ(OK, status)
97            << "consumer receiveDispatchSignal should return OK";
98
99    InputEvent* event;
100    status = mConsumer->consume(& mEventFactory, & event);
101    ASSERT_EQ(OK, status)
102            << "consumer consume should return OK";
103
104    ASSERT_TRUE(event != NULL)
105            << "consumer should have returned non-NULL event";
106    ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event->getType())
107            << "consumer should have returned a key event";
108
109    KeyEvent* keyEvent = static_cast<KeyEvent*>(event);
110    EXPECT_EQ(deviceId, keyEvent->getDeviceId());
111    EXPECT_EQ(source, keyEvent->getSource());
112    EXPECT_EQ(action, keyEvent->getAction());
113    EXPECT_EQ(flags, keyEvent->getFlags());
114    EXPECT_EQ(keyCode, keyEvent->getKeyCode());
115    EXPECT_EQ(scanCode, keyEvent->getScanCode());
116    EXPECT_EQ(metaState, keyEvent->getMetaState());
117    EXPECT_EQ(repeatCount, keyEvent->getRepeatCount());
118    EXPECT_EQ(downTime, keyEvent->getDownTime());
119    EXPECT_EQ(eventTime, keyEvent->getEventTime());
120
121    status = mConsumer->sendFinishedSignal();
122    ASSERT_EQ(OK, status)
123            << "consumer sendFinishedSignal should return OK";
124
125    status = mPublisher->receiveFinishedSignal();
126    ASSERT_EQ(OK, status)
127            << "publisher receiveFinishedSignal should return OK";
128
129    status = mPublisher->reset();
130    ASSERT_EQ(OK, status)
131            << "publisher reset should return OK";
132}
133
134void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
135        size_t samplesToAppendBeforeDispatch, size_t samplesToAppendAfterDispatch) {
136    status_t status;
137
138    const int32_t deviceId = 1;
139    const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
140    const int32_t action = AMOTION_EVENT_ACTION_MOVE;
141    const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
142    const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
143    const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
144    const float xOffset = -10;
145    const float yOffset = -20;
146    const float xPrecision = 0.25;
147    const float yPrecision = 0.5;
148    const nsecs_t downTime = 3;
149    const size_t pointerCount = 3;
150    const int32_t pointerIds[pointerCount] = { 2, 0, 1 };
151
152    Vector<nsecs_t> sampleEventTimes;
153    Vector<PointerCoords> samplePointerCoords;
154
155    for (size_t i = 0; i <= samplesToAppendAfterDispatch + samplesToAppendBeforeDispatch; i++) {
156        sampleEventTimes.push(i + 10);
157        for (size_t j = 0; j < pointerCount; j++) {
158            samplePointerCoords.push();
159            samplePointerCoords.editTop().x = 100 * i + j;
160            samplePointerCoords.editTop().y = 200 * i + j;
161            samplePointerCoords.editTop().pressure = 0.5 * i + j;
162            samplePointerCoords.editTop().size = 0.7 * i + j;
163            samplePointerCoords.editTop().touchMajor = 1.5 * i + j;
164            samplePointerCoords.editTop().touchMinor = 1.7 * i + j;
165            samplePointerCoords.editTop().toolMajor = 2.5 * i + j;
166            samplePointerCoords.editTop().toolMinor = 2.7 * i + j;
167            samplePointerCoords.editTop().orientation = 3.5 * i + j;
168        }
169    }
170
171    status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
172            metaState, xOffset, yOffset, xPrecision, yPrecision,
173            downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
174    ASSERT_EQ(OK, status)
175            << "publisher publishMotionEvent should return OK";
176
177    for (size_t i = 0; i < samplesToAppendBeforeDispatch; i++) {
178        size_t sampleIndex = i + 1;
179        status = mPublisher->appendMotionSample(sampleEventTimes[sampleIndex],
180                samplePointerCoords.array() + sampleIndex * pointerCount);
181        ASSERT_EQ(OK, status)
182                << "publisher appendMotionEvent should return OK";
183    }
184
185    status = mPublisher->sendDispatchSignal();
186    ASSERT_EQ(OK, status)
187            << "publisher sendDispatchSignal should return OK";
188
189    for (size_t i = 0; i < samplesToAppendAfterDispatch; i++) {
190        size_t sampleIndex = i + 1 + samplesToAppendBeforeDispatch;
191        status = mPublisher->appendMotionSample(sampleEventTimes[sampleIndex],
192                samplePointerCoords.array() + sampleIndex * pointerCount);
193        ASSERT_EQ(OK, status)
194                << "publisher appendMotionEvent should return OK";
195    }
196
197    status = mConsumer->receiveDispatchSignal();
198    ASSERT_EQ(OK, status)
199            << "consumer receiveDispatchSignal should return OK";
200
201    InputEvent* event;
202    status = mConsumer->consume(& mEventFactory, & event);
203    ASSERT_EQ(OK, status)
204            << "consumer consume should return OK";
205
206    ASSERT_TRUE(event != NULL)
207            << "consumer should have returned non-NULL event";
208    ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
209            << "consumer should have returned a motion event";
210
211    size_t lastSampleIndex = samplesToAppendBeforeDispatch + samplesToAppendAfterDispatch;
212
213    MotionEvent* motionEvent = static_cast<MotionEvent*>(event);
214    EXPECT_EQ(deviceId, motionEvent->getDeviceId());
215    EXPECT_EQ(source, motionEvent->getSource());
216    EXPECT_EQ(action, motionEvent->getAction());
217    EXPECT_EQ(flags, motionEvent->getFlags());
218    EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
219    EXPECT_EQ(metaState, motionEvent->getMetaState());
220    EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
221    EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
222    EXPECT_EQ(downTime, motionEvent->getDownTime());
223    EXPECT_EQ(sampleEventTimes[lastSampleIndex], motionEvent->getEventTime());
224    EXPECT_EQ(pointerCount, motionEvent->getPointerCount());
225    EXPECT_EQ(lastSampleIndex, motionEvent->getHistorySize());
226
227    for (size_t i = 0; i < pointerCount; i++) {
228        SCOPED_TRACE(i);
229        EXPECT_EQ(pointerIds[i], motionEvent->getPointerId(i));
230    }
231
232    for (size_t sampleIndex = 0; sampleIndex < lastSampleIndex; sampleIndex++) {
233        SCOPED_TRACE(sampleIndex);
234        EXPECT_EQ(sampleEventTimes[sampleIndex],
235                motionEvent->getHistoricalEventTime(sampleIndex));
236        for (size_t i = 0; i < pointerCount; i++) {
237            SCOPED_TRACE(i);
238            size_t offset = sampleIndex * pointerCount + i;
239            EXPECT_EQ(samplePointerCoords[offset].x,
240                    motionEvent->getHistoricalRawX(i, sampleIndex));
241            EXPECT_EQ(samplePointerCoords[offset].y,
242                    motionEvent->getHistoricalRawY(i, sampleIndex));
243            EXPECT_EQ(samplePointerCoords[offset].x + xOffset,
244                    motionEvent->getHistoricalX(i, sampleIndex));
245            EXPECT_EQ(samplePointerCoords[offset].y + yOffset,
246                    motionEvent->getHistoricalY(i, sampleIndex));
247            EXPECT_EQ(samplePointerCoords[offset].pressure,
248                    motionEvent->getHistoricalPressure(i, sampleIndex));
249            EXPECT_EQ(samplePointerCoords[offset].size,
250                    motionEvent->getHistoricalSize(i, sampleIndex));
251            EXPECT_EQ(samplePointerCoords[offset].touchMajor,
252                    motionEvent->getHistoricalTouchMajor(i, sampleIndex));
253            EXPECT_EQ(samplePointerCoords[offset].touchMinor,
254                    motionEvent->getHistoricalTouchMinor(i, sampleIndex));
255            EXPECT_EQ(samplePointerCoords[offset].toolMajor,
256                    motionEvent->getHistoricalToolMajor(i, sampleIndex));
257            EXPECT_EQ(samplePointerCoords[offset].toolMinor,
258                    motionEvent->getHistoricalToolMinor(i, sampleIndex));
259            EXPECT_EQ(samplePointerCoords[offset].orientation,
260                    motionEvent->getHistoricalOrientation(i, sampleIndex));
261        }
262    }
263
264    SCOPED_TRACE(lastSampleIndex);
265    EXPECT_EQ(sampleEventTimes[lastSampleIndex], motionEvent->getEventTime());
266    for (size_t i = 0; i < pointerCount; i++) {
267        SCOPED_TRACE(i);
268        size_t offset = lastSampleIndex * pointerCount + i;
269        EXPECT_EQ(samplePointerCoords[offset].x, motionEvent->getRawX(i));
270        EXPECT_EQ(samplePointerCoords[offset].y, motionEvent->getRawY(i));
271        EXPECT_EQ(samplePointerCoords[offset].x + xOffset, motionEvent->getX(i));
272        EXPECT_EQ(samplePointerCoords[offset].y + yOffset, motionEvent->getY(i));
273        EXPECT_EQ(samplePointerCoords[offset].pressure, motionEvent->getPressure(i));
274        EXPECT_EQ(samplePointerCoords[offset].size, motionEvent->getSize(i));
275        EXPECT_EQ(samplePointerCoords[offset].touchMajor, motionEvent->getTouchMajor(i));
276        EXPECT_EQ(samplePointerCoords[offset].touchMinor, motionEvent->getTouchMinor(i));
277        EXPECT_EQ(samplePointerCoords[offset].toolMajor, motionEvent->getToolMajor(i));
278        EXPECT_EQ(samplePointerCoords[offset].toolMinor, motionEvent->getToolMinor(i));
279        EXPECT_EQ(samplePointerCoords[offset].orientation, motionEvent->getOrientation(i));
280    }
281
282    status = mConsumer->sendFinishedSignal();
283    ASSERT_EQ(OK, status)
284            << "consumer sendFinishedSignal should return OK";
285
286    status = mPublisher->receiveFinishedSignal();
287    ASSERT_EQ(OK, status)
288            << "publisher receiveFinishedSignal should return OK";
289
290    status = mPublisher->reset();
291    ASSERT_EQ(OK, status)
292            << "publisher reset should return OK";
293}
294
295TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_EndToEnd) {
296    ASSERT_NO_FATAL_FAILURE(Initialize());
297    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
298}
299
300TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_WhenNotReset_ReturnsError) {
301    status_t status;
302    ASSERT_NO_FATAL_FAILURE(Initialize());
303
304    status = mPublisher->publishKeyEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
305    ASSERT_EQ(OK, status)
306            << "publisher publishKeyEvent should return OK first time";
307
308    status = mPublisher->publishKeyEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
309    ASSERT_EQ(INVALID_OPERATION, status)
310            << "publisher publishKeyEvent should return INVALID_OPERATION because "
311                    "the publisher was not reset";
312}
313
314TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_EndToEnd) {
315    ASSERT_NO_FATAL_FAILURE(Initialize());
316    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
317}
318
319TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsError) {
320    status_t status;
321    ASSERT_NO_FATAL_FAILURE(Initialize());
322
323    const size_t pointerCount = 1;
324    int32_t pointerIds[pointerCount] = { 0 };
325    PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
326
327    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
328            pointerCount, pointerIds, pointerCoords);
329    ASSERT_EQ(OK, status)
330            << "publisher publishMotionEvent should return OK";
331
332    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
333            pointerCount, pointerIds, pointerCoords);
334    ASSERT_EQ(INVALID_OPERATION, status)
335            << "publisher publishMotionEvent should return INVALID_OPERATION because ";
336                    "the publisher was not reset";
337}
338
339TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
340    status_t status;
341    ASSERT_NO_FATAL_FAILURE(Initialize());
342
343    const size_t pointerCount = 0;
344    int32_t pointerIds[pointerCount];
345    PointerCoords pointerCoords[pointerCount];
346
347    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
348            pointerCount, pointerIds, pointerCoords);
349    ASSERT_EQ(BAD_VALUE, status)
350            << "publisher publishMotionEvent should return BAD_VALUE";
351}
352
353TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
354    status_t status;
355    ASSERT_NO_FATAL_FAILURE(Initialize());
356
357    const size_t pointerCount = MAX_POINTERS + 1;
358    int32_t pointerIds[pointerCount];
359    PointerCoords pointerCoords[pointerCount];
360
361    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
362            pointerCount, pointerIds, pointerCoords);
363    ASSERT_EQ(BAD_VALUE, status)
364            << "publisher publishMotionEvent should return BAD_VALUE";
365}
366
367TEST_F(InputPublisherAndConsumerTest, PublishMultipleEvents_EndToEnd) {
368    ASSERT_NO_FATAL_FAILURE(Initialize());
369    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
370    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
371    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
372    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
373    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
374}
375
376TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenCalledBeforeDispatchSignal_AppendsSamples) {
377    status_t status;
378    ASSERT_NO_FATAL_FAILURE(Initialize());
379    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent(3, 0));
380}
381
382TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenCalledAfterDispatchSignalAndNotConsumed_AppendsSamples) {
383    status_t status;
384    ASSERT_NO_FATAL_FAILURE(Initialize());
385    ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent(0, 4));
386}
387
388TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenNoMotionEventPublished_ReturnsError) {
389    status_t status;
390    ASSERT_NO_FATAL_FAILURE(Initialize());
391
392    PointerCoords pointerCoords[1];
393    status = mPublisher->appendMotionSample(0, pointerCoords);
394    ASSERT_EQ(INVALID_OPERATION, status)
395            << "publisher appendMotionSample should return INVALID_OPERATION";
396}
397
398TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenPublishedMotionEventIsNotAMove_ReturnsError) {
399    status_t status;
400    ASSERT_NO_FATAL_FAILURE(Initialize());
401
402    const size_t pointerCount = MAX_POINTERS;
403    int32_t pointerIds[pointerCount];
404    PointerCoords pointerCoords[pointerCount];
405
406    status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
407            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
408    ASSERT_EQ(OK, status);
409
410    status = mPublisher->appendMotionSample(0, pointerCoords);
411    ASSERT_EQ(INVALID_OPERATION, status)
412            << "publisher appendMotionSample should return INVALID_OPERATION";
413}
414
415TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenAlreadyConsumed_ReturnsError) {
416    status_t status;
417    ASSERT_NO_FATAL_FAILURE(Initialize());
418
419    const size_t pointerCount = MAX_POINTERS;
420    int32_t pointerIds[pointerCount];
421    PointerCoords pointerCoords[pointerCount];
422
423    status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
424            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
425    ASSERT_EQ(OK, status);
426
427    status = mPublisher->sendDispatchSignal();
428    ASSERT_EQ(OK, status);
429
430    status = mConsumer->receiveDispatchSignal();
431    ASSERT_EQ(OK, status);
432
433    InputEvent* event;
434    status = mConsumer->consume(& mEventFactory, & event);
435    ASSERT_EQ(OK, status);
436
437    status = mPublisher->appendMotionSample(0, pointerCoords);
438    ASSERT_EQ(status_t(FAILED_TRANSACTION), status)
439            << "publisher appendMotionSample should return FAILED_TRANSACTION";
440}
441
442TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenBufferFull_ReturnsError) {
443    status_t status;
444    ASSERT_NO_FATAL_FAILURE(Initialize());
445
446    const size_t pointerCount = MAX_POINTERS;
447    int32_t pointerIds[pointerCount];
448    PointerCoords pointerCoords[pointerCount];
449
450    status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
451            0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
452    ASSERT_EQ(OK, status);
453
454    for (int count = 1;; count++) {
455        ASSERT_LT(count, 100000) << "should eventually reach OOM";
456
457        status = mPublisher->appendMotionSample(0, pointerCoords);
458        if (status != OK) {
459            ASSERT_GT(count, 12) << "should be able to add at least a dozen samples";
460            ASSERT_EQ(NO_MEMORY, status)
461                    << "publisher appendMotionSample should return NO_MEMORY when buffer is full";
462            break;
463        }
464    }
465
466    status = mPublisher->appendMotionSample(0, pointerCoords);
467    ASSERT_EQ(NO_MEMORY, status)
468            << "publisher appendMotionSample should return NO_MEMORY persistently until reset";
469}
470
471} // namespace android
472