InputDispatcher_test.cpp revision fe9f8ab03a63b1037f07dd85799fbea80ec6adaa
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    PointerProperties pointerProperties[MAX_POINTERS + 1];
146    PointerCoords pointerCoords[MAX_POINTERS + 1];
147    for (int i = 0; i <= MAX_POINTERS; i++) {
148        pointerProperties[i].clear();
149        pointerProperties[i].id = i;
150        pointerCoords[i].clear();
151    }
152
153    // Rejects undefined motion actions.
154    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
155            /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
156            ARBITRARY_TIME, ARBITRARY_TIME,
157            /*pointerCount*/ 1, pointerProperties, pointerCoords);
158    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
159            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
160            << "Should reject motion events with undefined action.";
161
162    // Rejects pointer down with invalid index.
163    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
164            AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
165            0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
166            ARBITRARY_TIME, ARBITRARY_TIME,
167            /*pointerCount*/ 1, pointerProperties, pointerCoords);
168    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
169            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
170            << "Should reject motion events with pointer down index too large.";
171
172    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
173            AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
174            0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
175            ARBITRARY_TIME, ARBITRARY_TIME,
176            /*pointerCount*/ 1, pointerProperties, pointerCoords);
177    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
178            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
179            << "Should reject motion events with pointer down index too small.";
180
181    // Rejects pointer up with invalid index.
182    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
183            AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
184            0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
185            ARBITRARY_TIME, ARBITRARY_TIME,
186            /*pointerCount*/ 1, pointerProperties, pointerCoords);
187    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
188            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
189            << "Should reject motion events with pointer up index too large.";
190
191    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
192            AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
193            0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
194            ARBITRARY_TIME, ARBITRARY_TIME,
195            /*pointerCount*/ 1, pointerProperties, pointerCoords);
196    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
197            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
198            << "Should reject motion events with pointer up index too small.";
199
200    // Rejects motion events with invalid number of pointers.
201    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
202            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
203            ARBITRARY_TIME, ARBITRARY_TIME,
204            /*pointerCount*/ 0, pointerProperties, pointerCoords);
205    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
206            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
207            << "Should reject motion events with 0 pointers.";
208
209    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
210            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
211            ARBITRARY_TIME, ARBITRARY_TIME,
212            /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
213    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
214            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
215            << "Should reject motion events with more than MAX_POINTERS pointers.";
216
217    // Rejects motion events with invalid pointer ids.
218    pointerProperties[0].id = -1;
219    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
220            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
221            ARBITRARY_TIME, ARBITRARY_TIME,
222            /*pointerCount*/ 1, pointerProperties, pointerCoords);
223    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
224            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
225            << "Should reject motion events with pointer ids less than 0.";
226
227    pointerProperties[0].id = MAX_POINTER_ID + 1;
228    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
229            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
230            ARBITRARY_TIME, ARBITRARY_TIME,
231            /*pointerCount*/ 1, pointerProperties, pointerCoords);
232    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
233            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
234            << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
235
236    // Rejects motion events with duplicate pointer ids.
237    pointerProperties[0].id = 1;
238    pointerProperties[1].id = 1;
239    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
240            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
241            ARBITRARY_TIME, ARBITRARY_TIME,
242            /*pointerCount*/ 2, pointerProperties, pointerCoords);
243    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
244            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
245            << "Should reject motion events with duplicate pointer ids.";
246}
247
248} // namespace android
249