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: 41 virtual ~FakeInputDispatcherPolicy() { 42 } 43 44 public: 45 FakeInputDispatcherPolicy() { 46 } 47 48 private: 49 virtual void notifyConfigurationChanged(nsecs_t when) { 50 } 51 52 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, 53 const sp<InputWindowHandle>& inputWindowHandle, 54 const String8& reason) { 55 return 0; 56 } 57 58 virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) { 59 } 60 61 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) { 62 *outConfig = mConfig; 63 } 64 65 virtual bool isKeyRepeatEnabled() { 66 return true; 67 } 68 69 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) { 70 return true; 71 } 72 73 virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) { 74 } 75 76 virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { 77 } 78 79 virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle, 80 const KeyEvent* keyEvent, uint32_t policyFlags) { 81 return 0; 82 } 83 84 virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle, 85 const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) { 86 return false; 87 } 88 89 virtual void notifySwitch(nsecs_t when, 90 uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) { 91 } 92 93 virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) { 94 } 95 96 virtual bool checkInjectEventsPermissionNonReentrant( 97 int32_t injectorPid, int32_t injectorUid) { 98 return false; 99 } 100 }; 101 102 103 // --- InputDispatcherTest --- 104 105 class InputDispatcherTest : public testing::Test { 106 protected: 107 sp<FakeInputDispatcherPolicy> mFakePolicy; 108 sp<InputDispatcher> mDispatcher; 109 110 virtual void SetUp() { 111 mFakePolicy = new FakeInputDispatcherPolicy(); 112 mDispatcher = new InputDispatcher(mFakePolicy); 113 } 114 115 virtual void TearDown() { 116 mFakePolicy.clear(); 117 mDispatcher.clear(); 118 } 119 }; 120 121 122 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) { 123 KeyEvent event; 124 125 // Rejects undefined key actions. 126 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, 127 /*action*/ -1, 0, 128 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); 129 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 130 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 131 << "Should reject key events with undefined action."; 132 133 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API. 134 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, 135 AKEY_EVENT_ACTION_MULTIPLE, 0, 136 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); 137 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 138 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 139 << "Should reject key events with ACTION_MULTIPLE."; 140 } 141 142 TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) { 143 MotionEvent event; 144 PointerProperties pointerProperties[MAX_POINTERS + 1]; 145 PointerCoords pointerCoords[MAX_POINTERS + 1]; 146 for (int i = 0; i <= MAX_POINTERS; i++) { 147 pointerProperties[i].clear(); 148 pointerProperties[i].id = i; 149 pointerCoords[i].clear(); 150 } 151 152 // Rejects undefined motion actions. 153 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 154 /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 155 ARBITRARY_TIME, ARBITRARY_TIME, 156 /*pointerCount*/ 1, pointerProperties, pointerCoords); 157 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 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, 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(&event, 168 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 169 << "Should reject motion events with pointer down index too large."; 170 171 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 172 AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 173 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 174 ARBITRARY_TIME, ARBITRARY_TIME, 175 /*pointerCount*/ 1, pointerProperties, pointerCoords); 176 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 177 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 178 << "Should reject motion events with pointer down index too small."; 179 180 // Rejects pointer up with invalid index. 181 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 182 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 183 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 184 ARBITRARY_TIME, ARBITRARY_TIME, 185 /*pointerCount*/ 1, pointerProperties, pointerCoords); 186 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 187 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 188 << "Should reject motion events with pointer up index too large."; 189 190 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 191 AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT), 192 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 193 ARBITRARY_TIME, ARBITRARY_TIME, 194 /*pointerCount*/ 1, pointerProperties, pointerCoords); 195 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 196 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 197 << "Should reject motion events with pointer up index too small."; 198 199 // Rejects motion events with invalid number of pointers. 200 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 201 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 202 ARBITRARY_TIME, ARBITRARY_TIME, 203 /*pointerCount*/ 0, pointerProperties, pointerCoords); 204 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 205 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 206 << "Should reject motion events with 0 pointers."; 207 208 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 209 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 210 ARBITRARY_TIME, ARBITRARY_TIME, 211 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords); 212 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 213 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 214 << "Should reject motion events with more than MAX_POINTERS pointers."; 215 216 // Rejects motion events with invalid pointer ids. 217 pointerProperties[0].id = -1; 218 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 219 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 220 ARBITRARY_TIME, ARBITRARY_TIME, 221 /*pointerCount*/ 1, pointerProperties, pointerCoords); 222 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 223 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 224 << "Should reject motion events with pointer ids less than 0."; 225 226 pointerProperties[0].id = MAX_POINTER_ID + 1; 227 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 228 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 229 ARBITRARY_TIME, ARBITRARY_TIME, 230 /*pointerCount*/ 1, pointerProperties, pointerCoords); 231 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 232 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 233 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID."; 234 235 // Rejects motion events with duplicate pointer ids. 236 pointerProperties[0].id = 1; 237 pointerProperties[1].id = 1; 238 event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, 239 AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0, 240 ARBITRARY_TIME, ARBITRARY_TIME, 241 /*pointerCount*/ 2, pointerProperties, pointerCoords); 242 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event, 243 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0)) 244 << "Should reject motion events with duplicate pointer ids."; 245 } 246 247 } // namespace android 248