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