• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 namespace android {
23 
24 // An arbitrary time value.
25 static const nsecs_t ARBITRARY_TIME = 1234;
26 
27 // An arbitrary device id.
28 static const int32_t DEVICE_ID = 1;
29 
30 // An arbitrary injector pid / uid pair that has permission to inject events.
31 static const int32_t INJECTOR_PID = 999;
32 static const int32_t INJECTOR_UID = 1001;
33 
34 
35 // --- FakeInputDispatcherPolicy ---
36 
37 class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
38     InputDispatcherConfiguration mConfig;
39 
40 protected:
~FakeInputDispatcherPolicy()41     virtual ~FakeInputDispatcherPolicy() {
42     }
43 
44 public:
FakeInputDispatcherPolicy()45     FakeInputDispatcherPolicy() {
46     }
47 
48 private:
notifyConfigurationChanged(nsecs_t when)49     virtual void notifyConfigurationChanged(nsecs_t when) {
50     }
51 
notifyANR(const sp<InputApplicationHandle> & inputApplicationHandle,const sp<InputWindowHandle> & inputWindowHandle)52     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
53             const sp<InputWindowHandle>& inputWindowHandle) {
54         return 0;
55     }
56 
notifyInputChannelBroken(const sp<InputWindowHandle> & inputWindowHandle)57     virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
58     }
59 
getDispatcherConfiguration(InputDispatcherConfiguration * outConfig)60     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
61         *outConfig = mConfig;
62     }
63 
isKeyRepeatEnabled()64     virtual bool isKeyRepeatEnabled() {
65         return true;
66     }
67 
filterInputEvent(const InputEvent * inputEvent,uint32_t policyFlags)68     virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
69         return true;
70     }
71 
interceptKeyBeforeQueueing(const KeyEvent * keyEvent,uint32_t & policyFlags)72     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
73     }
74 
interceptMotionBeforeQueueing(nsecs_t when,uint32_t & policyFlags)75     virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
76     }
77 
interceptKeyBeforeDispatching(const sp<InputWindowHandle> & inputWindowHandle,const KeyEvent * keyEvent,uint32_t policyFlags)78     virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
79             const KeyEvent* keyEvent, uint32_t policyFlags) {
80         return 0;
81     }
82 
dispatchUnhandledKey(const sp<InputWindowHandle> & inputWindowHandle,const KeyEvent * keyEvent,uint32_t policyFlags,KeyEvent * outFallbackKeyEvent)83     virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
84             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
85         return false;
86     }
87 
notifySwitch(nsecs_t when,int32_t switchCode,int32_t switchValue,uint32_t policyFlags)88     virtual void notifySwitch(nsecs_t when,
89             int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
90     }
91 
pokeUserActivity(nsecs_t eventTime,int32_t eventType)92     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
93     }
94 
checkInjectEventsPermissionNonReentrant(int32_t injectorPid,int32_t injectorUid)95     virtual bool checkInjectEventsPermissionNonReentrant(
96             int32_t injectorPid, int32_t injectorUid) {
97         return false;
98     }
99 };
100 
101 
102 // --- InputDispatcherTest ---
103 
104 class InputDispatcherTest : public testing::Test {
105 protected:
106     sp<FakeInputDispatcherPolicy> mFakePolicy;
107     sp<InputDispatcher> mDispatcher;
108 
SetUp()109     virtual void SetUp() {
110         mFakePolicy = new FakeInputDispatcherPolicy();
111         mDispatcher = new InputDispatcher(mFakePolicy);
112     }
113 
TearDown()114     virtual void TearDown() {
115         mFakePolicy.clear();
116         mDispatcher.clear();
117     }
118 };
119 
120 
TEST_F(InputDispatcherTest,InjectInputEvent_ValidatesKeyEvents)121 TEST_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 
TEST_F(InputDispatcherTest,InjectInputEvent_ValidatesMotionEvents)141 TEST_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