blob: 8c1991ea740deba1c6ec17593dea952fcc809dea [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
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
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tane84e6f92019-08-29 17:28:41 -070019#include <InputDispatcherThread.h>
20
Robert Carr803535b2018-08-02 16:38:15 -070021#include <binder/Binder.h>
22
Michael Wrightd02c5b62014-02-10 15:10:22 -080023#include <gtest/gtest.h>
24#include <linux/input.h>
25
Garfield Tane84e6f92019-08-29 17:28:41 -070026namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080027
28// An arbitrary time value.
29static const nsecs_t ARBITRARY_TIME = 1234;
30
31// An arbitrary device id.
32static const int32_t DEVICE_ID = 1;
33
Jeff Brownf086ddb2014-02-11 14:28:48 -080034// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080035static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080036
Michael Wrightd02c5b62014-02-10 15:10:22 -080037// An arbitrary injector pid / uid pair that has permission to inject events.
38static const int32_t INJECTOR_PID = 999;
39static const int32_t INJECTOR_UID = 1001;
40
41
42// --- FakeInputDispatcherPolicy ---
43
44class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
45 InputDispatcherConfiguration mConfig;
46
47protected:
48 virtual ~FakeInputDispatcherPolicy() {
49 }
50
51public:
52 FakeInputDispatcherPolicy() {
chaviwfd6d3512019-03-25 13:23:49 -070053 mOnPointerDownToken.clear();
Jackal Guof9696682018-10-05 12:23:23 +080054 }
55
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080056 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
57 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
58 ASSERT_EQ(mFilteredEvent->getType(), AINPUT_EVENT_TYPE_KEY);
Jackal Guof9696682018-10-05 12:23:23 +080059
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080060 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
61 ASSERT_EQ(keyEvent.getEventTime(), args.eventTime);
62 ASSERT_EQ(keyEvent.getAction(), args.action);
63 ASSERT_EQ(keyEvent.getDisplayId(), args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080064
65 reset();
66 }
67
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080068 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
69 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
70 ASSERT_EQ(mFilteredEvent->getType(), AINPUT_EVENT_TYPE_MOTION);
Jackal Guof9696682018-10-05 12:23:23 +080071
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080072 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
73 ASSERT_EQ(motionEvent.getEventTime(), args.eventTime);
74 ASSERT_EQ(motionEvent.getAction(), args.action);
75 ASSERT_EQ(motionEvent.getDisplayId(), args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080076
77 reset();
78 }
79
80 void assertFilterInputEventWasNotCalled() {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080081 ASSERT_EQ(nullptr, mFilteredEvent)
Jackal Guof9696682018-10-05 12:23:23 +080082 << "Expected filterInputEvent() to not have been called.";
Michael Wrightd02c5b62014-02-10 15:10:22 -080083 }
84
chaviwfd6d3512019-03-25 13:23:49 -070085 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
86 ASSERT_EQ(mOnPointerDownToken, touchedToken)
87 << "Expected token from onPointerDownOutsideFocus was not matched";
88 reset();
89 }
90
Michael Wrightd02c5b62014-02-10 15:10:22 -080091private:
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080092 std::unique_ptr<InputEvent> mFilteredEvent;
chaviwfd6d3512019-03-25 13:23:49 -070093 sp<IBinder> mOnPointerDownToken;
Jackal Guof9696682018-10-05 12:23:23 +080094
Narayan Kamath39efe3e2014-10-17 10:37:08 +010095 virtual void notifyConfigurationChanged(nsecs_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080096 }
97
Narayan Kamath39efe3e2014-10-17 10:37:08 +010098 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -070099 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800100 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800101 return 0;
102 }
103
Robert Carr803535b2018-08-02 16:38:15 -0700104 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800105 }
106
chaviw0c06c6e2019-01-09 13:27:07 -0800107 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700108 }
109
Michael Wrightd02c5b62014-02-10 15:10:22 -0800110 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
111 *outConfig = mConfig;
112 }
113
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800114 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Jackal Guof9696682018-10-05 12:23:23 +0800115 switch (inputEvent->getType()) {
116 case AINPUT_EVENT_TYPE_KEY: {
117 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800118 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800119 break;
120 }
121
122 case AINPUT_EVENT_TYPE_MOTION: {
123 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800124 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800125 break;
126 }
127 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800128 return true;
129 }
130
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100131 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800132 }
133
Charles Chen3611f1f2019-01-29 17:26:18 +0800134 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800135 }
136
Robert Carr803535b2018-08-02 16:38:15 -0700137 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100138 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800139 return 0;
140 }
141
Robert Carr803535b2018-08-02 16:38:15 -0700142 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100143 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800144 return false;
145 }
146
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100147 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800148 }
149
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100150 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800151 }
152
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100153 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154 return false;
155 }
Jackal Guof9696682018-10-05 12:23:23 +0800156
chaviwfd6d3512019-03-25 13:23:49 -0700157 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
158 mOnPointerDownToken = newToken;
159 }
160
Jackal Guof9696682018-10-05 12:23:23 +0800161 void reset() {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800162 mFilteredEvent = nullptr;
chaviwfd6d3512019-03-25 13:23:49 -0700163 mOnPointerDownToken.clear();
Jackal Guof9696682018-10-05 12:23:23 +0800164 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800165};
166
167
168// --- InputDispatcherTest ---
169
170class InputDispatcherTest : public testing::Test {
171protected:
172 sp<FakeInputDispatcherPolicy> mFakePolicy;
173 sp<InputDispatcher> mDispatcher;
Arthur Hungb92218b2018-08-14 12:00:21 +0800174 sp<InputDispatcherThread> mDispatcherThread;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800175
176 virtual void SetUp() {
177 mFakePolicy = new FakeInputDispatcherPolicy();
178 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800179 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
180 //Start InputDispatcher thread
181 mDispatcherThread = new InputDispatcherThread(mDispatcher);
182 mDispatcherThread->run("InputDispatcherTest", PRIORITY_URGENT_DISPLAY);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800183 }
184
185 virtual void TearDown() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800186 mDispatcherThread->requestExit();
187 mDispatcherThread.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188 mFakePolicy.clear();
189 mDispatcher.clear();
190 }
191};
192
193
194TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
195 KeyEvent event;
196
197 // Rejects undefined key actions.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100198 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800199 /*action*/ -1, 0,
200 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800201 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800202 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800203 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
204 << "Should reject key events with undefined action.";
205
206 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100207 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208 AKEY_EVENT_ACTION_MULTIPLE, 0,
209 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800210 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800211 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800212 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
213 << "Should reject key events with ACTION_MULTIPLE.";
214}
215
216TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
217 MotionEvent event;
218 PointerProperties pointerProperties[MAX_POINTERS + 1];
219 PointerCoords pointerCoords[MAX_POINTERS + 1];
220 for (int i = 0; i <= MAX_POINTERS; i++) {
221 pointerProperties[i].clear();
222 pointerProperties[i].id = i;
223 pointerCoords[i].clear();
224 }
225
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800226 // Some constants commonly used below
227 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
228 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
229 constexpr int32_t metaState = AMETA_NONE;
230 constexpr MotionClassification classification = MotionClassification::NONE;
231
Michael Wrightd02c5b62014-02-10 15:10:22 -0800232 // Rejects undefined motion actions.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800233 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700234 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
235 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
236 ARBITRARY_TIME, ARBITRARY_TIME,
237 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800238 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800239 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800240 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
241 << "Should reject motion events with undefined action.";
242
243 // Rejects pointer down with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800244 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700245 AMOTION_EVENT_ACTION_POINTER_DOWN |
246 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
247 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
248 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
249 ARBITRARY_TIME, ARBITRARY_TIME,
250 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800251 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800252 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800253 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
254 << "Should reject motion events with pointer down index too large.";
255
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800256 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700257 AMOTION_EVENT_ACTION_POINTER_DOWN |
258 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
259 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
260 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
261 ARBITRARY_TIME, ARBITRARY_TIME,
262 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800263 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800264 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800265 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
266 << "Should reject motion events with pointer down index too small.";
267
268 // Rejects pointer up with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800269 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700270 AMOTION_EVENT_ACTION_POINTER_UP |
271 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
272 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
273 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
274 ARBITRARY_TIME, ARBITRARY_TIME,
275 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800276 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800277 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800278 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
279 << "Should reject motion events with pointer up index too large.";
280
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800281 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Garfield Tan00f511d2019-06-12 16:55:40 -0700282 AMOTION_EVENT_ACTION_POINTER_UP |
283 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
284 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
285 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
286 ARBITRARY_TIME, ARBITRARY_TIME,
287 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800288 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800289 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800290 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
291 << "Should reject motion events with pointer up index too small.";
292
293 // Rejects motion events with invalid number of pointers.
Garfield Tan00f511d2019-06-12 16:55:40 -0700294 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
295 metaState, 0, classification, 0, 0, 0, 0,
296 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
297 ARBITRARY_TIME, ARBITRARY_TIME,
298 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800299 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800300 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
302 << "Should reject motion events with 0 pointers.";
303
Garfield Tan00f511d2019-06-12 16:55:40 -0700304 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
305 metaState, 0, classification, 0, 0, 0, 0,
306 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
307 ARBITRARY_TIME, ARBITRARY_TIME,
308 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800309 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800310 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800311 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
312 << "Should reject motion events with more than MAX_POINTERS pointers.";
313
314 // Rejects motion events with invalid pointer ids.
315 pointerProperties[0].id = -1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700316 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
317 metaState, 0, classification, 0, 0, 0, 0,
318 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
319 ARBITRARY_TIME, ARBITRARY_TIME,
320 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800321 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800322 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800323 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
324 << "Should reject motion events with pointer ids less than 0.";
325
326 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700327 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
328 metaState, 0, classification, 0, 0, 0, 0,
329 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
330 ARBITRARY_TIME, ARBITRARY_TIME,
331 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800332 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800333 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800334 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
335 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
336
337 // Rejects motion events with duplicate pointer ids.
338 pointerProperties[0].id = 1;
339 pointerProperties[1].id = 1;
Garfield Tan00f511d2019-06-12 16:55:40 -0700340 event.initialize(DEVICE_ID, source, DISPLAY_ID, AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags,
341 metaState, 0, classification, 0, 0, 0, 0,
342 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
343 ARBITRARY_TIME, ARBITRARY_TIME,
344 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800345 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800346 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800347 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
348 << "Should reject motion events with duplicate pointer ids.";
349}
350
Arthur Hungb92218b2018-08-14 12:00:21 +0800351// --- InputDispatcherTest SetInputWindowTest ---
352static const int32_t INJECT_EVENT_TIMEOUT = 500;
353static const int32_t DISPATCHING_TIMEOUT = 100;
354
355class FakeApplicationHandle : public InputApplicationHandle {
356public:
357 FakeApplicationHandle() {}
358 virtual ~FakeApplicationHandle() {}
359
360 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800361 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800362 return true;
363 }
364};
365
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800366class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800367public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800368 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
369 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800370 uint32_t consumeSeq;
371 InputEvent* event;
372 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
373 &consumeSeq, &event);
374
375 ASSERT_EQ(OK, status)
376 << mName.c_str() << ": consumer consume should return OK.";
377 ASSERT_TRUE(event != nullptr)
378 << mName.c_str() << ": consumer should have returned non-NULL event.";
379 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800380 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800381
382 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800383 << mName.c_str() << ": event displayId should be the same as expected.";
384
385 int32_t flags;
386 switch (expectedEventType) {
387 case AINPUT_EVENT_TYPE_KEY: {
388 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
389 flags = typedEvent->getFlags();
390 break;
391 }
392 case AINPUT_EVENT_TYPE_MOTION: {
393 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
394 flags = typedEvent->getFlags();
395 break;
396 }
397 default: {
398 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
399 }
400 }
401 ASSERT_EQ(expectedFlags, flags)
402 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800403
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800404 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800405 ASSERT_EQ(OK, status)
406 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
407 }
408
409 void assertNoEvents() {
410 uint32_t consumeSeq;
411 InputEvent* event;
412 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
413 &consumeSeq, &event);
414 ASSERT_NE(OK, status)
415 << mName.c_str()
416 << ": should not have received any events, so consume(..) should not return OK.";
417 }
418
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800419protected:
420 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
421 const std::string name, int32_t displayId) :
422 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
423 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
424 mConsumer = new InputConsumer(mClientChannel);
425 }
426
427 virtual ~FakeInputReceiver() {
428 }
429
430 // return true if the event has been handled.
431 virtual bool handled() {
432 return false;
433 }
434
Arthur Hungb92218b2018-08-14 12:00:21 +0800435 sp<InputDispatcher> mDispatcher;
436 sp<InputChannel> mServerChannel, mClientChannel;
437 InputConsumer *mConsumer;
438 PreallocatedInputEventFactory mEventFactory;
439
440 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800441 int32_t mDisplayId;
442};
443
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800444class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
445public:
446 static const int32_t WIDTH = 600;
447 static const int32_t HEIGHT = 800;
448
449 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
450 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800451 FakeInputReceiver(dispatcher, name, displayId),
chaviwfd6d3512019-03-25 13:23:49 -0700452 mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
Siarhei Vishniakou7c34b232019-10-11 19:08:48 -0700453 mDispatcher->registerInputChannel(mServerChannel);
chaviwfd6d3512019-03-25 13:23:49 -0700454
Robert Carr740167f2018-10-11 19:03:41 -0700455 inputApplicationHandle->updateInfo();
456 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800457 }
458
459 virtual bool updateInfo() {
Siarhei Vishniakou26d3cfb2019-10-15 17:02:32 -0700460 mInfo.token = mServerChannel ? mServerChannel->getConnectionToken() : nullptr;
Arthur Hung3b413f22018-10-26 18:05:34 +0800461 mInfo.name = mName;
chaviwfd6d3512019-03-25 13:23:49 -0700462 mInfo.layoutParamsFlags = mLayoutParamFlags;
Arthur Hung3b413f22018-10-26 18:05:34 +0800463 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
464 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwfd6d3512019-03-25 13:23:49 -0700465 mInfo.frameLeft = mFrame.left;
466 mInfo.frameTop = mFrame.top;
467 mInfo.frameRight = mFrame.right;
468 mInfo.frameBottom = mFrame.bottom;
Robert Carre07e1032018-11-26 12:55:53 -0800469 mInfo.globalScaleFactor = 1.0;
Garfield Tan00f511d2019-06-12 16:55:40 -0700470 mInfo.touchableRegion.clear();
chaviwfd6d3512019-03-25 13:23:49 -0700471 mInfo.addTouchableRegion(mFrame);
Arthur Hung3b413f22018-10-26 18:05:34 +0800472 mInfo.visible = true;
473 mInfo.canReceiveKeys = true;
474 mInfo.hasFocus = mFocused;
475 mInfo.hasWallpaper = false;
476 mInfo.paused = false;
477 mInfo.layer = 0;
478 mInfo.ownerPid = INJECTOR_PID;
479 mInfo.ownerUid = INJECTOR_UID;
480 mInfo.inputFeatures = 0;
481 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800482
483 return true;
484 }
485
486 void setFocus() {
487 mFocused = true;
488 }
Arthur Hung832bc4a2019-01-28 11:43:17 +0800489
chaviwfd6d3512019-03-25 13:23:49 -0700490 void setFrame(const Rect& frame) {
491 mFrame.set(frame);
492 }
493
494 void setLayoutParamFlags(int32_t flags) {
495 mLayoutParamFlags = flags;
496 }
497
Arthur Hung832bc4a2019-01-28 11:43:17 +0800498 void releaseChannel() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800499 mServerChannel.clear();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800500 InputWindowHandle::releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800501 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800502protected:
503 virtual bool handled() {
504 return true;
505 }
506
507 bool mFocused;
chaviwfd6d3512019-03-25 13:23:49 -0700508 Rect mFrame;
509 int32_t mLayoutParamFlags;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800510};
511
Tiger Huang721e26f2018-07-24 22:26:19 +0800512static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
513 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800514 KeyEvent event;
515 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
516
517 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800518 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800519 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
520 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
521
522 // Inject event until dispatch out.
523 return dispatcher->injectInputEvent(
524 &event,
525 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
526 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
527}
528
Garfield Tan00f511d2019-06-12 16:55:40 -0700529static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
530 int32_t source, int32_t displayId, int32_t x, int32_t y,
531 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
532 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800533 MotionEvent event;
534 PointerProperties pointerProperties[1];
535 PointerCoords pointerCoords[1];
536
537 pointerProperties[0].clear();
538 pointerProperties[0].id = 0;
539 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
540
541 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700542 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
543 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800544
545 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
546 // Define a valid motion down event.
Garfield Tan00f511d2019-06-12 16:55:40 -0700547 event.initialize(DEVICE_ID, source, displayId, action, /* actionButton */ 0, /* flags */ 0,
548 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
549 /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
550 /* yPrecision */ 0, xCursorPosition, yCursorPosition, currentTime, currentTime,
551 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800552
553 // Inject event until dispatch out.
554 return dispatcher->injectInputEvent(
555 &event,
556 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
557 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
558}
559
Garfield Tan00f511d2019-06-12 16:55:40 -0700560static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
561 int32_t displayId, int32_t x = 100, int32_t y = 200) {
562 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
563}
564
Jackal Guof9696682018-10-05 12:23:23 +0800565static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
566 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
567 // Define a valid key event.
568 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
569 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
570 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
571
572 return args;
573}
574
575static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
576 PointerProperties pointerProperties[1];
577 PointerCoords pointerCoords[1];
578
579 pointerProperties[0].clear();
580 pointerProperties[0].id = 0;
581 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
582
583 pointerCoords[0].clear();
584 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
585 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
586
587 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
588 // Define a valid motion event.
589 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700590 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
591 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -0700592 AMOTION_EVENT_EDGE_FLAG_NONE, 1, pointerProperties, pointerCoords,
593 /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700594 AMOTION_EVENT_INVALID_CURSOR_POSITION,
595 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800596
597 return args;
598}
599
Arthur Hungb92218b2018-08-14 12:00:21 +0800600TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
601 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800602 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
603 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800604
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800605 std::vector<sp<InputWindowHandle>> inputWindowHandles;
606 inputWindowHandles.push_back(window);
Arthur Hungb92218b2018-08-14 12:00:21 +0800607
608 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800609 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
610 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800611 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
612
613 // Window should receive motion event.
614 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
615}
616
617// The foreground window should receive the first touch down event.
618TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
619 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800620 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
621 ADISPLAY_ID_DEFAULT);
622 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
623 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800624
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800625 std::vector<sp<InputWindowHandle>> inputWindowHandles;
626 inputWindowHandles.push_back(windowTop);
627 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800628
629 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800630 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
631 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800632 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
633
634 // Top window should receive the touch down event. Second window should not receive anything.
635 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
636 windowSecond->assertNoEvents();
637}
638
639TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
640 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800641 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
642 ADISPLAY_ID_DEFAULT);
643 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
644 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800645
Arthur Hung7ab76b12019-01-09 19:17:20 +0800646 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800647 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800648
649 // Expect one focus window exist in display.
650 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800651 std::vector<sp<InputWindowHandle>> inputWindowHandles;
652 inputWindowHandles.push_back(windowTop);
653 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800654
655 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
656 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
657 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
658
659 // Focused window should receive event.
660 windowTop->assertNoEvents();
661 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
662}
663
Arthur Hung7ab76b12019-01-09 19:17:20 +0800664TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
665 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
666 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
667 ADISPLAY_ID_DEFAULT);
668 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
669 ADISPLAY_ID_DEFAULT);
670
671 // Set focused application.
672 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
673
674 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
675 windowTop->setFocus();
676 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800677 std::vector<sp<InputWindowHandle>> inputWindowHandles;
678 inputWindowHandles.push_back(windowTop);
679 inputWindowHandles.push_back(windowSecond);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800680
681 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
682 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
683 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
684
685 // Top focused window should receive event.
686 windowTop->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
687 windowSecond->assertNoEvents();
688}
689
Arthur Hung3b413f22018-10-26 18:05:34 +0800690TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
691 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
692
693 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
694 ADISPLAY_ID_DEFAULT);
695 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
696 ADISPLAY_ID_DEFAULT);
697
Arthur Hung832bc4a2019-01-28 11:43:17 +0800698 // Set focused application.
699 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800700
Arthur Hung832bc4a2019-01-28 11:43:17 +0800701 windowTop->setFocus();
702 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800703 std::vector<sp<InputWindowHandle>> inputWindowHandles;
704 inputWindowHandles.push_back(windowTop);
705 inputWindowHandles.push_back(windowSecond);
Arthur Hung3b413f22018-10-26 18:05:34 +0800706 // Release channel for window is no longer valid.
707 windowTop->releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800708 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung3b413f22018-10-26 18:05:34 +0800709
Arthur Hung832bc4a2019-01-28 11:43:17 +0800710 // Test inject a key down, should dispatch to a valid window.
711 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
712 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800713
714 // Top window is invalid, so it should not receive any input event.
715 windowTop->assertNoEvents();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800716 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800717}
718
Garfield Tan00f511d2019-06-12 16:55:40 -0700719TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
720 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
721
722 sp<FakeWindowHandle> windowLeft =
723 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
724 windowLeft->setFrame(Rect(0, 0, 600, 800));
725 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
726 sp<FakeWindowHandle> windowRight =
727 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
728 windowRight->setFrame(Rect(600, 0, 1200, 800));
729 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
730
731 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
732
733 std::vector<sp<InputWindowHandle>> inputWindowHandles{windowLeft, windowRight};
734 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
735
736 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
737 // left window. This event should be dispatched to the left window.
738 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
739 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
740 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
741 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
742 windowRight->assertNoEvents();
743}
744
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800745/* Test InputDispatcher for MultiDisplay */
746class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
747public:
748 static constexpr int32_t SECOND_DISPLAY_ID = 1;
749 virtual void SetUp() {
750 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800751
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800752 application1 = new FakeApplicationHandle();
753 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
754 ADISPLAY_ID_DEFAULT);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800755 std::vector<sp<InputWindowHandle>> inputWindowHandles;
756 inputWindowHandles.push_back(windowInPrimary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800757 // Set focus window for primary display, but focused display would be second one.
758 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
759 windowInPrimary->setFocus();
760 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800761
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800762 application2 = new FakeApplicationHandle();
763 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
764 SECOND_DISPLAY_ID);
765 // Set focus to second display window.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800766 std::vector<sp<InputWindowHandle>> inputWindowHandles_Second;
767 inputWindowHandles_Second.push_back(windowInSecondary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800768 // Set focus display to second one.
769 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
770 // Set focus window for second display.
771 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
772 windowInSecondary->setFocus();
773 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
774 }
775
776 virtual void TearDown() {
777 InputDispatcherTest::TearDown();
778
779 application1.clear();
780 windowInPrimary.clear();
781 application2.clear();
782 windowInSecondary.clear();
783 }
784
785protected:
786 sp<FakeApplicationHandle> application1;
787 sp<FakeWindowHandle> windowInPrimary;
788 sp<FakeApplicationHandle> application2;
789 sp<FakeWindowHandle> windowInSecondary;
790};
791
792TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
793 // Test touch down on primary display.
794 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
795 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800796 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
797 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
798 windowInSecondary->assertNoEvents();
799
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800800 // Test touch down on second display.
801 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
802 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800803 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
804 windowInPrimary->assertNoEvents();
805 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
806}
807
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800808TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800809 // Test inject a key down with display id specified.
810 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
811 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
812 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
813 windowInSecondary->assertNoEvents();
814
815 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800816 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
817 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
818 windowInPrimary->assertNoEvents();
819 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
820
821 // Remove secondary display.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800822 std::vector<sp<InputWindowHandle>> noWindows;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800823 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800824
825 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800826 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
827 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800828
829 // Test inject a key down, should timeout because of no target window.
830 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
831 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
832 windowInPrimary->assertNoEvents();
833 windowInSecondary->assertNoEvents();
834}
835
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800836class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
837public:
838 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
Michael Wright3dd60e22019-03-27 22:06:44 +0000839 int32_t displayId, bool isGestureMonitor = false)
840 : FakeInputReceiver(dispatcher, name, displayId) {
Michael Wright3dd60e22019-03-27 22:06:44 +0000841 mDispatcher->registerInputMonitor(mServerChannel, displayId, isGestureMonitor);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800842 }
843};
844
845// Test per-display input monitors for motion event.
846TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
847 sp<FakeMonitorReceiver> monitorInPrimary =
848 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
849 sp<FakeMonitorReceiver> monitorInSecondary =
850 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
851
852 // Test touch down on primary display.
853 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
854 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
855 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
856 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
857 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
858 windowInSecondary->assertNoEvents();
859 monitorInSecondary->assertNoEvents();
860
861 // Test touch down on second display.
862 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
863 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
864 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
865 windowInPrimary->assertNoEvents();
866 monitorInPrimary->assertNoEvents();
867 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
868 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
869
870 // Test inject a non-pointer motion event.
871 // If specific a display, it will dispatch to the focused window of particular display,
872 // or it will dispatch to the focused window of focused display.
873 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
874 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
875 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
876 windowInPrimary->assertNoEvents();
877 monitorInPrimary->assertNoEvents();
878 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
879 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
880}
881
882// Test per-display input monitors for key event.
883TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
884 //Input monitor per display.
885 sp<FakeMonitorReceiver> monitorInPrimary =
886 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
887 sp<FakeMonitorReceiver> monitorInSecondary =
888 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
889
890 // Test inject a key down.
891 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
892 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
893 windowInPrimary->assertNoEvents();
894 monitorInPrimary->assertNoEvents();
895 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
896 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
897}
898
Jackal Guof9696682018-10-05 12:23:23 +0800899class InputFilterTest : public InputDispatcherTest {
900protected:
901 static constexpr int32_t SECOND_DISPLAY_ID = 1;
902
903 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
904 NotifyMotionArgs motionArgs;
905
906 motionArgs = generateMotionArgs(
907 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
908 mDispatcher->notifyMotion(&motionArgs);
909 motionArgs = generateMotionArgs(
910 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
911 mDispatcher->notifyMotion(&motionArgs);
912
913 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800914 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +0800915 } else {
916 mFakePolicy->assertFilterInputEventWasNotCalled();
917 }
918 }
919
920 void testNotifyKey(bool expectToBeFiltered) {
921 NotifyKeyArgs keyArgs;
922
923 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
924 mDispatcher->notifyKey(&keyArgs);
925 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
926 mDispatcher->notifyKey(&keyArgs);
927
928 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800929 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +0800930 } else {
931 mFakePolicy->assertFilterInputEventWasNotCalled();
932 }
933 }
934};
935
936// Test InputFilter for MotionEvent
937TEST_F(InputFilterTest, MotionEvent_InputFilter) {
938 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
939 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
940 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
941
942 // Enable InputFilter
943 mDispatcher->setInputFilterEnabled(true);
944 // Test touch on both primary and second display, and check if both events are filtered.
945 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
946 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
947
948 // Disable InputFilter
949 mDispatcher->setInputFilterEnabled(false);
950 // Test touch on both primary and second display, and check if both events aren't filtered.
951 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
952 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
953}
954
955// Test InputFilter for KeyEvent
956TEST_F(InputFilterTest, KeyEvent_InputFilter) {
957 // Since the InputFilter is disabled by default, check if key event aren't filtered.
958 testNotifyKey(/*expectToBeFiltered*/ false);
959
960 // Enable InputFilter
961 mDispatcher->setInputFilterEnabled(true);
962 // Send a key event, and check if it is filtered.
963 testNotifyKey(/*expectToBeFiltered*/ true);
964
965 // Disable InputFilter
966 mDispatcher->setInputFilterEnabled(false);
967 // Send a key event, and check if it isn't filtered.
968 testNotifyKey(/*expectToBeFiltered*/ false);
969}
970
chaviwfd6d3512019-03-25 13:23:49 -0700971class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
972 virtual void SetUp() {
973 InputDispatcherTest::SetUp();
974
975 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
976 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
977 ADISPLAY_ID_DEFAULT);
978 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
979 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
980 // window.
981 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
982
983 mWindowFocused = new FakeWindowHandle(application, mDispatcher, "Second",
984 ADISPLAY_ID_DEFAULT);
985 mWindowFocused->setFrame(Rect(50, 50, 100, 100));
986 mWindowFocused->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
987 mWindowFocusedTouchPoint = 60;
988
989 // Set focused application.
990 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
991 mWindowFocused->setFocus();
992
993 // Expect one focus window exist in display.
994 std::vector<sp<InputWindowHandle>> inputWindowHandles;
995 inputWindowHandles.push_back(mUnfocusedWindow);
996 inputWindowHandles.push_back(mWindowFocused);
997 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
998 }
999
1000 virtual void TearDown() {
1001 InputDispatcherTest::TearDown();
1002
1003 mUnfocusedWindow.clear();
1004 mWindowFocused.clear();
1005 }
1006
1007protected:
1008 sp<FakeWindowHandle> mUnfocusedWindow;
1009 sp<FakeWindowHandle> mWindowFocused;
1010 int32_t mWindowFocusedTouchPoint;
1011};
1012
1013// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1014// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1015// the onPointerDownOutsideFocus callback.
1016TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
1017 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1018 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
1019 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1020 // Call monitor to wait for the command queue to get flushed.
1021 mDispatcher->monitor();
1022
1023 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1024}
1025
1026// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1027// DOWN on the window that doesn't have focus. Ensure no window received the
1028// onPointerDownOutsideFocus callback.
1029TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
1030 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1031 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
1032 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1033 // Call monitor to wait for the command queue to get flushed.
1034 mDispatcher->monitor();
1035
1036 mFakePolicy->assertOnPointerDownEquals(nullptr);
1037}
1038
1039// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1040// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1041TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1042 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1043 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1044 // Call monitor to wait for the command queue to get flushed.
1045 mDispatcher->monitor();
1046
1047 mFakePolicy->assertOnPointerDownEquals(nullptr);
1048}
1049
1050// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1051// DOWN on the window that already has focus. Ensure no window received the
1052// onPointerDownOutsideFocus callback.
1053TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1054 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
1055 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1056 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mWindowFocusedTouchPoint,
1057 mWindowFocusedTouchPoint))
1058 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1059 // Call monitor to wait for the command queue to get flushed.
1060 mDispatcher->monitor();
1061
1062 mFakePolicy->assertOnPointerDownEquals(nullptr);
1063}
1064
Garfield Tane84e6f92019-08-29 17:28:41 -07001065} // namespace android::inputdispatcher