InputDispatcher_test.cpp revision bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3
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 {
38    InputDispatcherConfiguration mConfig;
39
40protected:
41    virtual ~FakeInputDispatcherPolicy() {
42    }
43
44public:
45    FakeInputDispatcherPolicy() {
46    }
47
48private:
49    virtual void notifyConfigurationChanged(nsecs_t when) {
50    }
51
52    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
53            const sp<InputWindowHandle>& inputWindowHandle) {
54        return 0;
55    }
56
57    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
58    }
59
60    virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
61        *outConfig = mConfig;
62    }
63
64    virtual bool isKeyRepeatEnabled() {
65        return true;
66    }
67
68    virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
69        return true;
70    }
71
72    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
73    }
74
75    virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
76    }
77
78    virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
79            const KeyEvent* keyEvent, uint32_t policyFlags) {
80        return 0;
81    }
82
83    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
84            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
85        return false;
86    }
87
88    virtual void notifySwitch(nsecs_t when,
89            uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) {
90    }
91
92    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
93    }
94
95    virtual bool checkInjectEventsPermissionNonReentrant(
96            int32_t injectorPid, int32_t injectorUid) {
97        return false;
98    }
99};
100
101
102// --- InputDispatcherTest ---
103
104class InputDispatcherTest : public testing::Test {
105protected:
106    sp<FakeInputDispatcherPolicy> mFakePolicy;
107    sp<InputDispatcher> mDispatcher;
108
109    virtual void SetUp() {
110        mFakePolicy = new FakeInputDispatcherPolicy();
111        mDispatcher = new InputDispatcher(mFakePolicy);
112    }
113
114    virtual void TearDown() {
115        mFakePolicy.clear();
116        mDispatcher.clear();
117    }
118};
119
120
121TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
122    KeyEvent event;
123
124    // Rejects undefined key actions.
125    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
126            /*action*/ -1, 0,
127            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
128    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
129            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
130            << "Should reject key events with undefined action.";
131
132    // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
133    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
134            AKEY_EVENT_ACTION_MULTIPLE, 0,
135            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
136    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
137            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
138            << "Should reject key events with ACTION_MULTIPLE.";
139}
140
141TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
142    MotionEvent event;
143    PointerProperties pointerProperties[MAX_POINTERS + 1];
144    PointerCoords pointerCoords[MAX_POINTERS + 1];
145    for (int i = 0; i <= MAX_POINTERS; i++) {
146        pointerProperties[i].clear();
147        pointerProperties[i].id = i;
148        pointerCoords[i].clear();
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, 0,
154            ARBITRARY_TIME, ARBITRARY_TIME,
155            /*pointerCount*/ 1, pointerProperties, 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, 0,
164            ARBITRARY_TIME, ARBITRARY_TIME,
165            /*pointerCount*/ 1, pointerProperties, 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, 0,
173            ARBITRARY_TIME, ARBITRARY_TIME,
174            /*pointerCount*/ 1, pointerProperties, 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, 0,
183            ARBITRARY_TIME, ARBITRARY_TIME,
184            /*pointerCount*/ 1, pointerProperties, 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, 0,
192            ARBITRARY_TIME, ARBITRARY_TIME,
193            /*pointerCount*/ 1, pointerProperties, 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, 0,
201            ARBITRARY_TIME, ARBITRARY_TIME,
202            /*pointerCount*/ 0, pointerProperties, 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, 0,
209            ARBITRARY_TIME, ARBITRARY_TIME,
210            /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, 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    pointerProperties[0].id = -1;
217    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
218            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
219            ARBITRARY_TIME, ARBITRARY_TIME,
220            /*pointerCount*/ 1, pointerProperties, 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    pointerProperties[0].id = 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, 0,
228            ARBITRARY_TIME, ARBITRARY_TIME,
229            /*pointerCount*/ 1, pointerProperties, 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    pointerProperties[0].id = 1;
236    pointerProperties[1].id = 1;
237    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
238            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
239            ARBITRARY_TIME, ARBITRARY_TIME,
240            /*pointerCount*/ 2, pointerProperties, 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