blob: f0c36e5b05e4a68118dee14ea76f2917c2bffc33 [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
17#include "../InputDispatcher.h"
18
Robert Carr803535b2018-08-02 16:38:15 -070019#include <binder/Binder.h>
20
Michael Wrightd02c5b62014-02-10 15:10:22 -080021#include <gtest/gtest.h>
22#include <linux/input.h>
23
24namespace android {
25
26// An arbitrary time value.
27static const nsecs_t ARBITRARY_TIME = 1234;
28
29// An arbitrary device id.
30static const int32_t DEVICE_ID = 1;
31
Jeff Brownf086ddb2014-02-11 14:28:48 -080032// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080033static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080034
Michael Wrightd02c5b62014-02-10 15:10:22 -080035// An arbitrary injector pid / uid pair that has permission to inject events.
36static const int32_t INJECTOR_PID = 999;
37static const int32_t INJECTOR_UID = 1001;
38
39
40// --- FakeInputDispatcherPolicy ---
41
42class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
43 InputDispatcherConfiguration mConfig;
44
45protected:
46 virtual ~FakeInputDispatcherPolicy() {
47 }
48
49public:
50 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080051 mInputEventFiltered = false;
52 mTime = -1;
53 mAction = -1;
54 mDisplayId = -1;
chaviwfd6d3512019-03-25 13:23:49 -070055 mOnPointerDownToken.clear();
Jackal Guof9696682018-10-05 12:23:23 +080056 }
57
58 void assertFilterInputEventWasCalledWithExpectedArgs(const NotifyMotionArgs* args) {
59 ASSERT_TRUE(mInputEventFiltered)
60 << "Expected filterInputEvent() to have been called.";
61
62 ASSERT_EQ(mTime, args->eventTime)
63 << "Expected time of filtered event was not matched";
64 ASSERT_EQ(mAction, args->action)
65 << "Expected action of filtered event was not matched";
66 ASSERT_EQ(mDisplayId, args->displayId)
67 << "Expected displayId of filtered event was not matched";
68
69 reset();
70 }
71
72 void assertFilterInputEventWasCalledWithExpectedArgs(const NotifyKeyArgs* args) {
73 ASSERT_TRUE(mInputEventFiltered)
74 << "Expected filterInputEvent() to have been called.";
75
76 ASSERT_EQ(mTime, args->eventTime)
77 << "Expected time of filtered event was not matched";
78 ASSERT_EQ(mAction, args->action)
79 << "Expected action of filtered event was not matched";
80 ASSERT_EQ(mDisplayId, args->displayId)
81 << "Expected displayId of filtered event was not matched";
82
83 reset();
84 }
85
86 void assertFilterInputEventWasNotCalled() {
87 ASSERT_FALSE(mInputEventFiltered)
88 << "Expected filterInputEvent() to not have been called.";
Michael Wrightd02c5b62014-02-10 15:10:22 -080089 }
90
chaviwfd6d3512019-03-25 13:23:49 -070091 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
92 ASSERT_EQ(mOnPointerDownToken, touchedToken)
93 << "Expected token from onPointerDownOutsideFocus was not matched";
94 reset();
95 }
96
Michael Wrightd02c5b62014-02-10 15:10:22 -080097private:
Jackal Guof9696682018-10-05 12:23:23 +080098 bool mInputEventFiltered;
99 nsecs_t mTime;
100 int32_t mAction;
101 int32_t mDisplayId;
chaviwfd6d3512019-03-25 13:23:49 -0700102 sp<IBinder> mOnPointerDownToken;
Jackal Guof9696682018-10-05 12:23:23 +0800103
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100104 virtual void notifyConfigurationChanged(nsecs_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800105 }
106
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100107 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -0700108 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800109 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800110 return 0;
111 }
112
Robert Carr803535b2018-08-02 16:38:15 -0700113 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800114 }
115
chaviw0c06c6e2019-01-09 13:27:07 -0800116 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700117 }
118
Michael Wrightd02c5b62014-02-10 15:10:22 -0800119 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
120 *outConfig = mConfig;
121 }
122
Jackal Guof9696682018-10-05 12:23:23 +0800123 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
124 switch (inputEvent->getType()) {
125 case AINPUT_EVENT_TYPE_KEY: {
126 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
127 mTime = keyEvent->getEventTime();
128 mAction = keyEvent->getAction();
129 mDisplayId = keyEvent->getDisplayId();
130 break;
131 }
132
133 case AINPUT_EVENT_TYPE_MOTION: {
134 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
135 mTime = motionEvent->getEventTime();
136 mAction = motionEvent->getAction();
137 mDisplayId = motionEvent->getDisplayId();
138 break;
139 }
140 }
141
142 mInputEventFiltered = true;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800143 return true;
144 }
145
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100146 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800147 }
148
Charles Chen3611f1f2019-01-29 17:26:18 +0800149 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800150 }
151
Robert Carr803535b2018-08-02 16:38:15 -0700152 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100153 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154 return 0;
155 }
156
Robert Carr803535b2018-08-02 16:38:15 -0700157 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100158 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800159 return false;
160 }
161
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100162 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800163 }
164
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100165 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800166 }
167
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100168 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800169 return false;
170 }
Jackal Guof9696682018-10-05 12:23:23 +0800171
chaviwfd6d3512019-03-25 13:23:49 -0700172 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
173 mOnPointerDownToken = newToken;
174 }
175
Jackal Guof9696682018-10-05 12:23:23 +0800176 void reset() {
177 mInputEventFiltered = false;
178 mTime = -1;
179 mAction = -1;
180 mDisplayId = -1;
chaviwfd6d3512019-03-25 13:23:49 -0700181 mOnPointerDownToken.clear();
Jackal Guof9696682018-10-05 12:23:23 +0800182 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800183};
184
185
186// --- InputDispatcherTest ---
187
188class InputDispatcherTest : public testing::Test {
189protected:
190 sp<FakeInputDispatcherPolicy> mFakePolicy;
191 sp<InputDispatcher> mDispatcher;
Arthur Hungb92218b2018-08-14 12:00:21 +0800192 sp<InputDispatcherThread> mDispatcherThread;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800193
194 virtual void SetUp() {
195 mFakePolicy = new FakeInputDispatcherPolicy();
196 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800197 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
198 //Start InputDispatcher thread
199 mDispatcherThread = new InputDispatcherThread(mDispatcher);
200 mDispatcherThread->run("InputDispatcherTest", PRIORITY_URGENT_DISPLAY);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800201 }
202
203 virtual void TearDown() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800204 mDispatcherThread->requestExit();
205 mDispatcherThread.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800206 mFakePolicy.clear();
207 mDispatcher.clear();
208 }
209};
210
211
212TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
213 KeyEvent event;
214
215 // Rejects undefined key actions.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100216 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800217 /*action*/ -1, 0,
218 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800219 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800220 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800221 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
222 << "Should reject key events with undefined action.";
223
224 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100225 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800226 AKEY_EVENT_ACTION_MULTIPLE, 0,
227 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800228 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800229 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800230 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
231 << "Should reject key events with ACTION_MULTIPLE.";
232}
233
234TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
235 MotionEvent event;
236 PointerProperties pointerProperties[MAX_POINTERS + 1];
237 PointerCoords pointerCoords[MAX_POINTERS + 1];
238 for (int i = 0; i <= MAX_POINTERS; i++) {
239 pointerProperties[i].clear();
240 pointerProperties[i].id = i;
241 pointerCoords[i].clear();
242 }
243
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800244 // Some constants commonly used below
245 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
246 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
247 constexpr int32_t metaState = AMETA_NONE;
248 constexpr MotionClassification classification = MotionClassification::NONE;
249
Michael Wrightd02c5b62014-02-10 15:10:22 -0800250 // Rejects undefined motion actions.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800251 event.initialize(DEVICE_ID, source, DISPLAY_ID,
252 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
253 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800254 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800255 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800256 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
257 << "Should reject motion events with undefined action.";
258
259 // Rejects pointer down with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800260 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800261 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800262 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
263 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800264 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800265 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800266 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
267 << "Should reject motion events with pointer down index too large.";
268
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800269 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800270 AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800271 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
272 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800273 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800274 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800275 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
276 << "Should reject motion events with pointer down index too small.";
277
278 // Rejects pointer up with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800279 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800280 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800281 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
282 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800283 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800284 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800285 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
286 << "Should reject motion events with pointer up index too large.";
287
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800288 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800289 AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800290 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
291 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800292 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800293 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800294 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
295 << "Should reject motion events with pointer up index too small.";
296
297 // Rejects motion events with invalid number of pointers.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800298 event.initialize(DEVICE_ID, source, DISPLAY_ID,
299 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
300 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800301 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800302 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800303 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
304 << "Should reject motion events with 0 pointers.";
305
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800306 event.initialize(DEVICE_ID, source, DISPLAY_ID,
307 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 ARBITRARY_TIME, ARBITRARY_TIME,
309 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800310 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800311 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800312 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
313 << "Should reject motion events with more than MAX_POINTERS pointers.";
314
315 // Rejects motion events with invalid pointer ids.
316 pointerProperties[0].id = -1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800317 event.initialize(DEVICE_ID, source, DISPLAY_ID,
318 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
319 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800320 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800321 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800322 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
323 << "Should reject motion events with pointer ids less than 0.";
324
325 pointerProperties[0].id = MAX_POINTER_ID + 1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800326 event.initialize(DEVICE_ID, source, DISPLAY_ID,
327 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
328 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800329 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800330 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800331 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
332 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
333
334 // Rejects motion events with duplicate pointer ids.
335 pointerProperties[0].id = 1;
336 pointerProperties[1].id = 1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800337 event.initialize(DEVICE_ID, source, DISPLAY_ID,
338 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
339 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800340 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800341 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800342 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
343 << "Should reject motion events with duplicate pointer ids.";
344}
345
Arthur Hungb92218b2018-08-14 12:00:21 +0800346// --- InputDispatcherTest SetInputWindowTest ---
347static const int32_t INJECT_EVENT_TIMEOUT = 500;
348static const int32_t DISPATCHING_TIMEOUT = 100;
349
350class FakeApplicationHandle : public InputApplicationHandle {
351public:
352 FakeApplicationHandle() {}
353 virtual ~FakeApplicationHandle() {}
354
355 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800356 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800357 return true;
358 }
359};
360
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800361class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800362public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800363 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
364 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800365 uint32_t consumeSeq;
366 InputEvent* event;
367 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
368 &consumeSeq, &event);
369
370 ASSERT_EQ(OK, status)
371 << mName.c_str() << ": consumer consume should return OK.";
372 ASSERT_TRUE(event != nullptr)
373 << mName.c_str() << ": consumer should have returned non-NULL event.";
374 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800375 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800376
377 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800378 << mName.c_str() << ": event displayId should be the same as expected.";
379
380 int32_t flags;
381 switch (expectedEventType) {
382 case AINPUT_EVENT_TYPE_KEY: {
383 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
384 flags = typedEvent->getFlags();
385 break;
386 }
387 case AINPUT_EVENT_TYPE_MOTION: {
388 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
389 flags = typedEvent->getFlags();
390 break;
391 }
392 default: {
393 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
394 }
395 }
396 ASSERT_EQ(expectedFlags, flags)
397 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800398
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800399 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800400 ASSERT_EQ(OK, status)
401 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
402 }
403
404 void assertNoEvents() {
405 uint32_t consumeSeq;
406 InputEvent* event;
407 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
408 &consumeSeq, &event);
409 ASSERT_NE(OK, status)
410 << mName.c_str()
411 << ": should not have received any events, so consume(..) should not return OK.";
412 }
413
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800414protected:
415 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
416 const std::string name, int32_t displayId) :
417 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
418 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
419 mConsumer = new InputConsumer(mClientChannel);
420 }
421
422 virtual ~FakeInputReceiver() {
423 }
424
425 // return true if the event has been handled.
426 virtual bool handled() {
427 return false;
428 }
429
Arthur Hungb92218b2018-08-14 12:00:21 +0800430 sp<InputDispatcher> mDispatcher;
431 sp<InputChannel> mServerChannel, mClientChannel;
Robert Carr5c8a0262018-10-03 16:30:44 -0700432 sp<IBinder> mToken;
Arthur Hungb92218b2018-08-14 12:00:21 +0800433 InputConsumer *mConsumer;
434 PreallocatedInputEventFactory mEventFactory;
435
436 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800437 int32_t mDisplayId;
438};
439
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800440class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
441public:
442 static const int32_t WIDTH = 600;
443 static const int32_t HEIGHT = 800;
444
445 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
446 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800447 FakeInputReceiver(dispatcher, name, displayId),
chaviwfd6d3512019-03-25 13:23:49 -0700448 mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
Robert Carr4e670e52018-08-15 13:26:12 -0700449 mServerChannel->setToken(new BBinder());
Robert Carr803535b2018-08-02 16:38:15 -0700450 mDispatcher->registerInputChannel(mServerChannel, displayId);
chaviwfd6d3512019-03-25 13:23:49 -0700451
Robert Carr740167f2018-10-11 19:03:41 -0700452 inputApplicationHandle->updateInfo();
453 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800454 }
455
456 virtual bool updateInfo() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800457 mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
Arthur Hung3b413f22018-10-26 18:05:34 +0800458 mInfo.name = mName;
chaviwfd6d3512019-03-25 13:23:49 -0700459 mInfo.layoutParamsFlags = mLayoutParamFlags;
Arthur Hung3b413f22018-10-26 18:05:34 +0800460 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
461 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwfd6d3512019-03-25 13:23:49 -0700462 mInfo.frameLeft = mFrame.left;
463 mInfo.frameTop = mFrame.top;
464 mInfo.frameRight = mFrame.right;
465 mInfo.frameBottom = mFrame.bottom;
Robert Carre07e1032018-11-26 12:55:53 -0800466 mInfo.globalScaleFactor = 1.0;
chaviwfd6d3512019-03-25 13:23:49 -0700467 mInfo.addTouchableRegion(mFrame);
Arthur Hung3b413f22018-10-26 18:05:34 +0800468 mInfo.visible = true;
469 mInfo.canReceiveKeys = true;
470 mInfo.hasFocus = mFocused;
471 mInfo.hasWallpaper = false;
472 mInfo.paused = false;
473 mInfo.layer = 0;
474 mInfo.ownerPid = INJECTOR_PID;
475 mInfo.ownerUid = INJECTOR_UID;
476 mInfo.inputFeatures = 0;
477 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800478
479 return true;
480 }
481
482 void setFocus() {
483 mFocused = true;
484 }
Arthur Hung832bc4a2019-01-28 11:43:17 +0800485
chaviwfd6d3512019-03-25 13:23:49 -0700486 void setFrame(const Rect& frame) {
487 mFrame.set(frame);
488 }
489
490 void setLayoutParamFlags(int32_t flags) {
491 mLayoutParamFlags = flags;
492 }
493
Arthur Hung832bc4a2019-01-28 11:43:17 +0800494 void releaseChannel() {
Arthur Hung6b5a2b92019-01-31 16:39:28 +0800495 mServerChannel.clear();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800496 InputWindowHandle::releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800497 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800498protected:
499 virtual bool handled() {
500 return true;
501 }
502
503 bool mFocused;
chaviwfd6d3512019-03-25 13:23:49 -0700504 Rect mFrame;
505 int32_t mLayoutParamFlags;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800506};
507
Tiger Huang721e26f2018-07-24 22:26:19 +0800508static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
509 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800510 KeyEvent event;
511 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
512
513 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800514 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800515 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
516 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
517
518 // Inject event until dispatch out.
519 return dispatcher->injectInputEvent(
520 &event,
521 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
522 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
523}
524
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800525static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
chaviwfd6d3512019-03-25 13:23:49 -0700526 int32_t displayId, int32_t x = 100, int32_t y = 200) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800527 MotionEvent event;
528 PointerProperties pointerProperties[1];
529 PointerCoords pointerCoords[1];
530
531 pointerProperties[0].clear();
532 pointerProperties[0].id = 0;
533 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
534
535 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700536 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
537 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800538
539 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
540 // Define a valid motion down event.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800541 event.initialize(DEVICE_ID, source, displayId,
chaviwfd6d3512019-03-25 13:23:49 -0700542 AMOTION_EVENT_ACTION_DOWN, /* actionButton */ 0, /* flags */ 0, /* edgeFlags */ 0,
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800543 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
544 /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
Arthur Hungb92218b2018-08-14 12:00:21 +0800545 /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
546 pointerCoords);
547
548 // Inject event until dispatch out.
549 return dispatcher->injectInputEvent(
550 &event,
551 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
552 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
553}
554
Jackal Guof9696682018-10-05 12:23:23 +0800555static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
556 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
557 // Define a valid key event.
558 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
559 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
560 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
561
562 return args;
563}
564
565static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
566 PointerProperties pointerProperties[1];
567 PointerCoords pointerCoords[1];
568
569 pointerProperties[0].clear();
570 pointerProperties[0].id = 0;
571 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
572
573 pointerCoords[0].clear();
574 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
575 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
576
577 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
578 // Define a valid motion event.
579 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
580 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
581 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
582 AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1, pointerProperties,
583 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0, currentTime,
584 /* videoFrames */ {});
585
586 return args;
587}
588
Arthur Hungb92218b2018-08-14 12:00:21 +0800589TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
590 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800591 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
592 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800593
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800594 std::vector<sp<InputWindowHandle>> inputWindowHandles;
595 inputWindowHandles.push_back(window);
Arthur Hungb92218b2018-08-14 12:00:21 +0800596
597 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800598 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
599 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800600 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
601
602 // Window should receive motion event.
603 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
604}
605
606// The foreground window should receive the first touch down event.
607TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
608 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800609 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
610 ADISPLAY_ID_DEFAULT);
611 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
612 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800613
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800614 std::vector<sp<InputWindowHandle>> inputWindowHandles;
615 inputWindowHandles.push_back(windowTop);
616 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800617
618 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800619 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
620 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800621 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
622
623 // Top window should receive the touch down event. Second window should not receive anything.
624 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
625 windowSecond->assertNoEvents();
626}
627
628TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
629 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800630 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
631 ADISPLAY_ID_DEFAULT);
632 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
633 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800634
Arthur Hung7ab76b12019-01-09 19:17:20 +0800635 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800636 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800637
638 // Expect one focus window exist in display.
639 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800640 std::vector<sp<InputWindowHandle>> inputWindowHandles;
641 inputWindowHandles.push_back(windowTop);
642 inputWindowHandles.push_back(windowSecond);
Arthur Hungb92218b2018-08-14 12:00:21 +0800643
644 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
645 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
646 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
647
648 // Focused window should receive event.
649 windowTop->assertNoEvents();
650 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
651}
652
Arthur Hung7ab76b12019-01-09 19:17:20 +0800653TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
654 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
655 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
656 ADISPLAY_ID_DEFAULT);
657 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
658 ADISPLAY_ID_DEFAULT);
659
660 // Set focused application.
661 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
662
663 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
664 windowTop->setFocus();
665 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800666 std::vector<sp<InputWindowHandle>> inputWindowHandles;
667 inputWindowHandles.push_back(windowTop);
668 inputWindowHandles.push_back(windowSecond);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800669
670 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
671 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
672 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
673
674 // Top focused window should receive event.
675 windowTop->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
676 windowSecond->assertNoEvents();
677}
678
Arthur Hung3b413f22018-10-26 18:05:34 +0800679TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
680 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
681
682 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
683 ADISPLAY_ID_DEFAULT);
684 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
685 ADISPLAY_ID_DEFAULT);
686
Arthur Hung832bc4a2019-01-28 11:43:17 +0800687 // Set focused application.
688 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800689
Arthur Hung832bc4a2019-01-28 11:43:17 +0800690 windowTop->setFocus();
691 windowSecond->setFocus();
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800692 std::vector<sp<InputWindowHandle>> inputWindowHandles;
693 inputWindowHandles.push_back(windowTop);
694 inputWindowHandles.push_back(windowSecond);
Arthur Hung3b413f22018-10-26 18:05:34 +0800695 // Release channel for window is no longer valid.
696 windowTop->releaseChannel();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800697 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung3b413f22018-10-26 18:05:34 +0800698
Arthur Hung832bc4a2019-01-28 11:43:17 +0800699 // Test inject a key down, should dispatch to a valid window.
700 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
701 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800702
703 // Top window is invalid, so it should not receive any input event.
704 windowTop->assertNoEvents();
Arthur Hung832bc4a2019-01-28 11:43:17 +0800705 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800706}
707
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800708/* Test InputDispatcher for MultiDisplay */
709class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
710public:
711 static constexpr int32_t SECOND_DISPLAY_ID = 1;
712 virtual void SetUp() {
713 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800714
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800715 application1 = new FakeApplicationHandle();
716 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
717 ADISPLAY_ID_DEFAULT);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800718 std::vector<sp<InputWindowHandle>> inputWindowHandles;
719 inputWindowHandles.push_back(windowInPrimary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800720 // Set focus window for primary display, but focused display would be second one.
721 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
722 windowInPrimary->setFocus();
723 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800724
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800725 application2 = new FakeApplicationHandle();
726 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
727 SECOND_DISPLAY_ID);
728 // Set focus to second display window.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800729 std::vector<sp<InputWindowHandle>> inputWindowHandles_Second;
730 inputWindowHandles_Second.push_back(windowInSecondary);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800731 // Set focus display to second one.
732 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
733 // Set focus window for second display.
734 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
735 windowInSecondary->setFocus();
736 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
737 }
738
739 virtual void TearDown() {
740 InputDispatcherTest::TearDown();
741
742 application1.clear();
743 windowInPrimary.clear();
744 application2.clear();
745 windowInSecondary.clear();
746 }
747
748protected:
749 sp<FakeApplicationHandle> application1;
750 sp<FakeWindowHandle> windowInPrimary;
751 sp<FakeApplicationHandle> application2;
752 sp<FakeWindowHandle> windowInSecondary;
753};
754
755TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
756 // Test touch down on primary display.
757 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
758 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800759 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
760 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
761 windowInSecondary->assertNoEvents();
762
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800763 // Test touch down on second display.
764 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
765 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800766 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
767 windowInPrimary->assertNoEvents();
768 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
769}
770
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800771TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800772 // Test inject a key down with display id specified.
773 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
774 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
775 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
776 windowInSecondary->assertNoEvents();
777
778 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800779 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
780 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
781 windowInPrimary->assertNoEvents();
782 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
783
784 // Remove secondary display.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800785 std::vector<sp<InputWindowHandle>> noWindows;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800786 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800787
788 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800789 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
790 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800791
792 // Test inject a key down, should timeout because of no target window.
793 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
794 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
795 windowInPrimary->assertNoEvents();
796 windowInSecondary->assertNoEvents();
797}
798
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800799class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
800public:
801 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
802 int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
Robert Carr803535b2018-08-02 16:38:15 -0700803 mDispatcher->registerInputChannel(mServerChannel, displayId);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800804 }
805};
806
807// Test per-display input monitors for motion event.
808TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
809 sp<FakeMonitorReceiver> monitorInPrimary =
810 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
811 sp<FakeMonitorReceiver> monitorInSecondary =
812 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
813
814 // Test touch down on primary display.
815 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
816 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
817 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
818 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
819 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
820 windowInSecondary->assertNoEvents();
821 monitorInSecondary->assertNoEvents();
822
823 // Test touch down on second display.
824 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
825 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
826 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
827 windowInPrimary->assertNoEvents();
828 monitorInPrimary->assertNoEvents();
829 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
830 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
831
832 // Test inject a non-pointer motion event.
833 // If specific a display, it will dispatch to the focused window of particular display,
834 // or it will dispatch to the focused window of focused display.
835 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
836 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
837 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
838 windowInPrimary->assertNoEvents();
839 monitorInPrimary->assertNoEvents();
840 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
841 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
842}
843
844// Test per-display input monitors for key event.
845TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
846 //Input monitor per display.
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 inject a key down.
853 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
854 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
855 windowInPrimary->assertNoEvents();
856 monitorInPrimary->assertNoEvents();
857 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
858 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
859}
860
Jackal Guof9696682018-10-05 12:23:23 +0800861class InputFilterTest : public InputDispatcherTest {
862protected:
863 static constexpr int32_t SECOND_DISPLAY_ID = 1;
864
865 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
866 NotifyMotionArgs motionArgs;
867
868 motionArgs = generateMotionArgs(
869 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
870 mDispatcher->notifyMotion(&motionArgs);
871 motionArgs = generateMotionArgs(
872 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
873 mDispatcher->notifyMotion(&motionArgs);
874
875 if (expectToBeFiltered) {
876 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&motionArgs);
877 } else {
878 mFakePolicy->assertFilterInputEventWasNotCalled();
879 }
880 }
881
882 void testNotifyKey(bool expectToBeFiltered) {
883 NotifyKeyArgs keyArgs;
884
885 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
886 mDispatcher->notifyKey(&keyArgs);
887 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
888 mDispatcher->notifyKey(&keyArgs);
889
890 if (expectToBeFiltered) {
891 mFakePolicy->assertFilterInputEventWasCalledWithExpectedArgs(&keyArgs);
892 } else {
893 mFakePolicy->assertFilterInputEventWasNotCalled();
894 }
895 }
896};
897
898// Test InputFilter for MotionEvent
899TEST_F(InputFilterTest, MotionEvent_InputFilter) {
900 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
901 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
902 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
903
904 // Enable InputFilter
905 mDispatcher->setInputFilterEnabled(true);
906 // Test touch on both primary and second display, and check if both events are filtered.
907 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
908 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
909
910 // Disable InputFilter
911 mDispatcher->setInputFilterEnabled(false);
912 // Test touch on both primary and second display, and check if both events aren't filtered.
913 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
914 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
915}
916
917// Test InputFilter for KeyEvent
918TEST_F(InputFilterTest, KeyEvent_InputFilter) {
919 // Since the InputFilter is disabled by default, check if key event aren't filtered.
920 testNotifyKey(/*expectToBeFiltered*/ false);
921
922 // Enable InputFilter
923 mDispatcher->setInputFilterEnabled(true);
924 // Send a key event, and check if it is filtered.
925 testNotifyKey(/*expectToBeFiltered*/ true);
926
927 // Disable InputFilter
928 mDispatcher->setInputFilterEnabled(false);
929 // Send a key event, and check if it isn't filtered.
930 testNotifyKey(/*expectToBeFiltered*/ false);
931}
932
chaviwfd6d3512019-03-25 13:23:49 -0700933class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
934 virtual void SetUp() {
935 InputDispatcherTest::SetUp();
936
937 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
938 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
939 ADISPLAY_ID_DEFAULT);
940 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
941 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
942 // window.
943 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
944
945 mWindowFocused = new FakeWindowHandle(application, mDispatcher, "Second",
946 ADISPLAY_ID_DEFAULT);
947 mWindowFocused->setFrame(Rect(50, 50, 100, 100));
948 mWindowFocused->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
949 mWindowFocusedTouchPoint = 60;
950
951 // Set focused application.
952 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
953 mWindowFocused->setFocus();
954
955 // Expect one focus window exist in display.
956 std::vector<sp<InputWindowHandle>> inputWindowHandles;
957 inputWindowHandles.push_back(mUnfocusedWindow);
958 inputWindowHandles.push_back(mWindowFocused);
959 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
960 }
961
962 virtual void TearDown() {
963 InputDispatcherTest::TearDown();
964
965 mUnfocusedWindow.clear();
966 mWindowFocused.clear();
967 }
968
969protected:
970 sp<FakeWindowHandle> mUnfocusedWindow;
971 sp<FakeWindowHandle> mWindowFocused;
972 int32_t mWindowFocusedTouchPoint;
973};
974
975// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
976// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
977// the onPointerDownOutsideFocus callback.
978TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
979 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
980 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
981 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
982 // Call monitor to wait for the command queue to get flushed.
983 mDispatcher->monitor();
984
985 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
986}
987
988// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
989// DOWN on the window that doesn't have focus. Ensure no window received the
990// onPointerDownOutsideFocus callback.
991TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
992 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
993 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
994 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
995 // Call monitor to wait for the command queue to get flushed.
996 mDispatcher->monitor();
997
998 mFakePolicy->assertOnPointerDownEquals(nullptr);
999}
1000
1001// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1002// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1003TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1004 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1005 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1006 // Call monitor to wait for the command queue to get flushed.
1007 mDispatcher->monitor();
1008
1009 mFakePolicy->assertOnPointerDownEquals(nullptr);
1010}
1011
1012// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1013// DOWN on the window that already has focus. Ensure no window received the
1014// onPointerDownOutsideFocus callback.
1015TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1016 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
1017 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1018 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mWindowFocusedTouchPoint,
1019 mWindowFocusedTouchPoint))
1020 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1021 // Call monitor to wait for the command queue to get flushed.
1022 mDispatcher->monitor();
1023
1024 mFakePolicy->assertOnPointerDownEquals(nullptr);
1025}
1026
Michael Wrightd02c5b62014-02-10 15:10:22 -08001027} // namespace android