InputDispatcher_test.cpp revision 928e054931d357326613c78e62f4d850b7c442ff
1//
2// Copyright 2010 The Android Open Source Project
3//
4
5#include "../InputDispatcher.h"
6
7#include <gtest/gtest.h>
8#include <linux/input.h>
9
10namespace android {
11
12// An arbitrary time value.
13static const nsecs_t ARBITRARY_TIME = 1234;
14
15// An arbitrary device id.
16static const int32_t DEVICE_ID = 1;
17
18// An arbitrary injector pid / uid pair that has permission to inject events.
19static const int32_t INJECTOR_PID = 999;
20static const int32_t INJECTOR_UID = 1001;
21
22
23// --- FakeInputDispatcherPolicy ---
24
25class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
26protected:
27    virtual ~FakeInputDispatcherPolicy() {
28    }
29
30public:
31    FakeInputDispatcherPolicy() {
32    }
33
34private:
35    virtual void notifyConfigurationChanged(nsecs_t when) {
36    }
37
38    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
39            const sp<InputWindowHandle>& inputWindowHandle) {
40        return 0;
41    }
42
43    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
44    }
45
46    virtual nsecs_t getKeyRepeatTimeout() {
47        return 500 * 1000000LL;
48    }
49
50    virtual nsecs_t getKeyRepeatDelay() {
51        return 50 * 1000000LL;
52    }
53
54    virtual int32_t getMaxEventsPerSecond() {
55        return 60;
56    }
57
58    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
59    }
60
61    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
62    }
63
64    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
65            const KeyEvent* keyEvent, uint32_t policyFlags) {
66        return false;
67    }
68
69    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
70            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
71        return false;
72    }
73
74    virtual void notifySwitch(nsecs_t when,
75            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
76    }
77
78    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
79    }
80
81    virtual bool checkInjectEventsPermissionNonReentrant(
82            int32_t injectorPid, int32_t injectorUid) {
83        return false;
84    }
85};
86
87
88// --- InputDispatcherTest ---
89
90class InputDispatcherTest : public testing::Test {
91protected:
92    sp<FakeInputDispatcherPolicy> mFakePolicy;
93    sp<InputDispatcher> mDispatcher;
94
95    virtual void SetUp() {
96        mFakePolicy = new FakeInputDispatcherPolicy();
97        mDispatcher = new InputDispatcher(mFakePolicy);
98    }
99
100    virtual void TearDown() {
101        mFakePolicy.clear();
102        mDispatcher.clear();
103    }
104};
105
106
107TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
108    KeyEvent event;
109
110    // Rejects undefined key actions.
111    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
112            /*action*/ -1, 0,
113            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
114    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
115            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
116            << "Should reject key events with undefined action.";
117
118    // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
119    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
120            AKEY_EVENT_ACTION_MULTIPLE, 0,
121            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
122    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
123            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
124            << "Should reject key events with ACTION_MULTIPLE.";
125}
126
127TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
128    MotionEvent event;
129    int32_t pointerIds[MAX_POINTERS + 1];
130    PointerCoords pointerCoords[MAX_POINTERS + 1];
131    for (int i = 0; i <= MAX_POINTERS; i++) {
132        pointerIds[i] = i;
133    }
134
135    // Rejects undefined motion actions.
136    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
137            /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
138            ARBITRARY_TIME, ARBITRARY_TIME,
139            /*pointerCount*/ 1, pointerIds, pointerCoords);
140    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
141            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
142            << "Should reject motion events with undefined action.";
143
144    // Rejects pointer down with invalid index.
145    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
146            AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
147            0, 0, AMETA_NONE, 0, 0, 0, 0,
148            ARBITRARY_TIME, ARBITRARY_TIME,
149            /*pointerCount*/ 1, pointerIds, pointerCoords);
150    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
151            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
152            << "Should reject motion events with pointer down index too large.";
153
154    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
155            AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
156            0, 0, AMETA_NONE, 0, 0, 0, 0,
157            ARBITRARY_TIME, ARBITRARY_TIME,
158            /*pointerCount*/ 1, pointerIds, pointerCoords);
159    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
160            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
161            << "Should reject motion events with pointer down index too small.";
162
163    // Rejects pointer up with invalid index.
164    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
165            AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
166            0, 0, AMETA_NONE, 0, 0, 0, 0,
167            ARBITRARY_TIME, ARBITRARY_TIME,
168            /*pointerCount*/ 1, pointerIds, pointerCoords);
169    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
170            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
171            << "Should reject motion events with pointer up index too large.";
172
173    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
174            AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
175            0, 0, AMETA_NONE, 0, 0, 0, 0,
176            ARBITRARY_TIME, ARBITRARY_TIME,
177            /*pointerCount*/ 1, pointerIds, pointerCoords);
178    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
179            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
180            << "Should reject motion events with pointer up index too small.";
181
182    // Rejects motion events with invalid number of pointers.
183    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
184            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
185            ARBITRARY_TIME, ARBITRARY_TIME,
186            /*pointerCount*/ 0, pointerIds, pointerCoords);
187    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
188            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
189            << "Should reject motion events with 0 pointers.";
190
191    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
192            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
193            ARBITRARY_TIME, ARBITRARY_TIME,
194            /*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
195    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
196            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
197            << "Should reject motion events with more than MAX_POINTERS pointers.";
198
199    // Rejects motion events with invalid pointer ids.
200    pointerIds[0] = -1;
201    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
202            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
203            ARBITRARY_TIME, ARBITRARY_TIME,
204            /*pointerCount*/ 1, pointerIds, pointerCoords);
205    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
206            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
207            << "Should reject motion events with pointer ids less than 0.";
208
209    pointerIds[0] = MAX_POINTER_ID + 1;
210    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
211            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
212            ARBITRARY_TIME, ARBITRARY_TIME,
213            /*pointerCount*/ 1, pointerIds, pointerCoords);
214    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
215            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
216            << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
217
218    // Rejects motion events with duplicate pointer ids.
219    pointerIds[0] = 1;
220    pointerIds[1] = 1;
221    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
222            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
223            ARBITRARY_TIME, ARBITRARY_TIME,
224            /*pointerCount*/ 2, pointerIds, pointerCoords);
225    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
226            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
227            << "Should reject motion events with duplicate pointer ids.";
228}
229
230} // namespace android
231