InputDispatcher_test.cpp revision 214eaf48878bba00cbd5831871bcbd82632b6e34
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 void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
69    }
70
71    virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
72    }
73
74    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
75            const KeyEvent* keyEvent, uint32_t policyFlags) {
76        return false;
77    }
78
79    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
80            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
81        return false;
82    }
83
84    virtual void notifySwitch(nsecs_t when,
85            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
86    }
87
88    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
89    }
90
91    virtual bool checkInjectEventsPermissionNonReentrant(
92            int32_t injectorPid, int32_t injectorUid) {
93        return false;
94    }
95};
96
97
98// --- InputDispatcherTest ---
99
100class InputDispatcherTest : public testing::Test {
101protected:
102    sp<FakeInputDispatcherPolicy> mFakePolicy;
103    sp<InputDispatcher> mDispatcher;
104
105    virtual void SetUp() {
106        mFakePolicy = new FakeInputDispatcherPolicy();
107        mDispatcher = new InputDispatcher(mFakePolicy);
108    }
109
110    virtual void TearDown() {
111        mFakePolicy.clear();
112        mDispatcher.clear();
113    }
114};
115
116
117TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
118    KeyEvent event;
119
120    // Rejects undefined key actions.
121    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
122            /*action*/ -1, 0,
123            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
124    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
125            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
126            << "Should reject key events with undefined action.";
127
128    // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
129    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
130            AKEY_EVENT_ACTION_MULTIPLE, 0,
131            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
132    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
133            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
134            << "Should reject key events with ACTION_MULTIPLE.";
135}
136
137TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
138    MotionEvent event;
139    int32_t pointerIds[MAX_POINTERS + 1];
140    PointerCoords pointerCoords[MAX_POINTERS + 1];
141    for (int i = 0; i <= MAX_POINTERS; i++) {
142        pointerIds[i] = i;
143    }
144
145    // Rejects undefined motion actions.
146    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
147            /*action*/ -1, 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 undefined action.";
153
154    // Rejects pointer down with invalid index.
155    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
156            AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
157            0, 0, AMETA_NONE, 0, 0, 0, 0,
158            ARBITRARY_TIME, ARBITRARY_TIME,
159            /*pointerCount*/ 1, pointerIds, pointerCoords);
160    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
161            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
162            << "Should reject motion events with pointer down index too large.";
163
164    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
165            AMOTION_EVENT_ACTION_POINTER_DOWN | (-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 down index too small.";
172
173    // Rejects pointer up with invalid index.
174    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
175            AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
176            0, 0, AMETA_NONE, 0, 0, 0, 0,
177            ARBITRARY_TIME, ARBITRARY_TIME,
178            /*pointerCount*/ 1, pointerIds, pointerCoords);
179    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
180            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
181            << "Should reject motion events with pointer up index too large.";
182
183    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
184            AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
185            0, 0, AMETA_NONE, 0, 0, 0, 0,
186            ARBITRARY_TIME, ARBITRARY_TIME,
187            /*pointerCount*/ 1, pointerIds, pointerCoords);
188    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
189            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
190            << "Should reject motion events with pointer up index too small.";
191
192    // Rejects motion events with invalid number of pointers.
193    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
194            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
195            ARBITRARY_TIME, ARBITRARY_TIME,
196            /*pointerCount*/ 0, pointerIds, pointerCoords);
197    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
198            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
199            << "Should reject motion events with 0 pointers.";
200
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*/ MAX_POINTERS + 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 more than MAX_POINTERS pointers.";
208
209    // Rejects motion events with invalid pointer ids.
210    pointerIds[0] = -1;
211    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
212            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
213            ARBITRARY_TIME, ARBITRARY_TIME,
214            /*pointerCount*/ 1, pointerIds, pointerCoords);
215    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
216            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
217            << "Should reject motion events with pointer ids less than 0.";
218
219    pointerIds[0] = MAX_POINTER_ID + 1;
220    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
221            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
222            ARBITRARY_TIME, ARBITRARY_TIME,
223            /*pointerCount*/ 1, pointerIds, pointerCoords);
224    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
225            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
226            << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
227
228    // Rejects motion events with duplicate pointer ids.
229    pointerIds[0] = 1;
230    pointerIds[1] = 1;
231    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
232            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
233            ARBITRARY_TIME, ARBITRARY_TIME,
234            /*pointerCount*/ 2, pointerIds, pointerCoords);
235    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
236            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
237            << "Should reject motion events with duplicate pointer ids.";
238}
239
240} // namespace android
241