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 display id. 31 static const int32_t DISPLAY_ID = 0; 32 33 // An arbitrary injector pid / uid pair that has permission to inject events. 34 static const int32_t INJECTOR_PID = 999; 35 static const int32_t INJECTOR_UID = 1001; 36 37 38 // --- FakeInputDispatcherPolicy --- 39 40 class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface { 41 InputDispatcherConfiguration mConfig; 42 43 protected: 44 virtual ~FakeInputDispatcherPolicy() { 45 } 46 47 public: 48 FakeInputDispatcherPolicy() { 49 } 50 51 private: 52 virtual void notifyConfigurationChanged(nsecs_t) { 53 } 54 55 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&, 56 const sp<InputWindowHandle>&, 57 const String8&) { 58 return 0; 59 } 60 61 virtual void notifyInputChannelBroken(const sp<InputWindowHandle>&) { 62 } 63 64 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) { 65 *outConfig = mConfig; 66 } 67 68 virtual bool filterInputEvent(const InputEvent*, uint32_t) { 69 return true; 70 } 71 72 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) { 73 } 74 75 virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) { 76 } 77 78 virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>&, 79 const KeyEvent*, uint32_t) { 80 return 0; 81 } 82 83 virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>&, 84 const KeyEvent*, uint32_t, KeyEvent*) { 85 return false; 86 } 87 88 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) { 89 } 90 91 virtual void pokeUserActivity(nsecs_t, int32_t) { 92 } 93 94 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) { 95 return false; 96 } 97 }; 98 99 100 // --- InputDispatcherTest --- 101 102 class InputDispatcherTest : public testing::Test { 103 protected: 104 sp<FakeInputDispatcherPolicy> mFakePolicy; 105 sp<InputDispatcher> mDispatcher; 106 107 virtual void SetUp() { 108 mFakePolicy = new FakeInputDispatcherPolicy(); 109 mDispatcher = new InputDispatcher(mFakePolicy); 110 } 111 112 virtual void TearDown() { 113 mFakePolicy.clear(); 114 mDispatcher.clear(); 115 } 116 }; 117 118 119 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) { 120 KeyEvent event; 121 122 // Rejects undefined key actions. 123 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, 124 /*action*/ -1, 0, 125 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); 126 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 127 &event, DISPLAY_ID, 128 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 129 << "Should reject key events with undefined action."; 130 131 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API. 132 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, 133 AKEY_EVENT_ACTION_MULTIPLE, 0, 134 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); 135 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 136 &event, DISPLAY_ID, 137 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 138 << "Should reject key events with ACTION_MULTIPLE."; 139 } 140 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, 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( 157 &event, DISPLAY_ID, 158 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 159 << "Should reject motion events with undefined action."; 160 161 // Rejects pointer down with invalid index. 162 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 163 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 164 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 165 ARBITRARY_TIME, ARBITRARY_TIME, 166 /*pointerCount*/ 1, pointerProperties, pointerCoords); 167 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 168 &event, DISPLAY_ID, 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 | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 174 0, 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( 178 &event, DISPLAY_ID, 179 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 180 << "Should reject motion events with pointer down index too small."; 181 182 // Rejects pointer up with invalid index. 183 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 184 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 185 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 186 ARBITRARY_TIME, ARBITRARY_TIME, 187 /*pointerCount*/ 1, pointerProperties, pointerCoords); 188 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 189 &event, DISPLAY_ID, 190 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 191 << "Should reject motion events with pointer up index too large."; 192 193 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 194 AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 195 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 196 ARBITRARY_TIME, ARBITRARY_TIME, 197 /*pointerCount*/ 1, pointerProperties, pointerCoords); 198 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 199 &event, DISPLAY_ID, 200 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 201 << "Should reject motion events with pointer up index too small."; 202 203 // Rejects motion events with invalid number of pointers. 204 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 205 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 206 ARBITRARY_TIME, ARBITRARY_TIME, 207 /*pointerCount*/ 0, pointerProperties, pointerCoords); 208 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 209 &event, DISPLAY_ID, 210 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 211 << "Should reject motion events with 0 pointers."; 212 213 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 214 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 215 ARBITRARY_TIME, ARBITRARY_TIME, 216 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords); 217 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 218 &event, DISPLAY_ID, 219 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 220 << "Should reject motion events with more than MAX_POINTERS pointers."; 221 222 // Rejects motion events with invalid pointer ids. 223 pointerProperties[0].id = -1; 224 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 225 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 226 ARBITRARY_TIME, ARBITRARY_TIME, 227 /*pointerCount*/ 1, pointerProperties, pointerCoords); 228 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 229 &event, DISPLAY_ID, 230 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 231 << "Should reject motion events with pointer ids less than 0."; 232 233 pointerProperties[0].id = MAX_POINTER_ID + 1; 234 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 235 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 236 ARBITRARY_TIME, ARBITRARY_TIME, 237 /*pointerCount*/ 1, pointerProperties, pointerCoords); 238 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 239 &event, DISPLAY_ID, 240 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 241 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID."; 242 243 // Rejects motion events with duplicate pointer ids. 244 pointerProperties[0].id = 1; 245 pointerProperties[1].id = 1; 246 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 247 AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 248 ARBITRARY_TIME, ARBITRARY_TIME, 249 /*pointerCount*/ 2, pointerProperties, pointerCoords); 250 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent( 251 &event, DISPLAY_ID, 252 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 253 << "Should reject motion events with duplicate pointer ids."; 254 } 255 256 } // namespace android 257