blob: 704c13ace2d4569e994eb4ee9fb085ef53b2e487 [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() {
51 }
52
53private:
Narayan Kamath39efe3e2014-10-17 10:37:08 +010054 virtual void notifyConfigurationChanged(nsecs_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080055 }
56
Narayan Kamath39efe3e2014-10-17 10:37:08 +010057 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -070058 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -080059 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080060 return 0;
61 }
62
Robert Carr803535b2018-08-02 16:38:15 -070063 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080064 }
65
Robert Carr740167f2018-10-11 19:03:41 -070066 virtual void notifyFocusChanged(const sp<IBinder>&) {
67 }
68
Michael Wrightd02c5b62014-02-10 15:10:22 -080069 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
70 *outConfig = mConfig;
71 }
72
Narayan Kamath39efe3e2014-10-17 10:37:08 +010073 virtual bool filterInputEvent(const InputEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080074 return true;
75 }
76
Narayan Kamath39efe3e2014-10-17 10:37:08 +010077 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080078 }
79
Narayan Kamath39efe3e2014-10-17 10:37:08 +010080 virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080081 }
82
Robert Carr803535b2018-08-02 16:38:15 -070083 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +010084 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080085 return 0;
86 }
87
Robert Carr803535b2018-08-02 16:38:15 -070088 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +010089 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080090 return false;
91 }
92
Narayan Kamath39efe3e2014-10-17 10:37:08 +010093 virtual void notifySwitch(nsecs_t, uint32_t, uint32_t, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080094 }
95
Narayan Kamath39efe3e2014-10-17 10:37:08 +010096 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -080097 }
98
Narayan Kamath39efe3e2014-10-17 10:37:08 +010099 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800100 return false;
101 }
102};
103
104
105// --- InputDispatcherTest ---
106
107class InputDispatcherTest : public testing::Test {
108protected:
109 sp<FakeInputDispatcherPolicy> mFakePolicy;
110 sp<InputDispatcher> mDispatcher;
Arthur Hungb92218b2018-08-14 12:00:21 +0800111 sp<InputDispatcherThread> mDispatcherThread;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800112
113 virtual void SetUp() {
114 mFakePolicy = new FakeInputDispatcherPolicy();
115 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800116 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
117 //Start InputDispatcher thread
118 mDispatcherThread = new InputDispatcherThread(mDispatcher);
119 mDispatcherThread->run("InputDispatcherTest", PRIORITY_URGENT_DISPLAY);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800120 }
121
122 virtual void TearDown() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800123 mDispatcherThread->requestExit();
124 mDispatcherThread.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800125 mFakePolicy.clear();
126 mDispatcher.clear();
127 }
128};
129
130
131TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
132 KeyEvent event;
133
134 // Rejects undefined key actions.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100135 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800136 /*action*/ -1, 0,
137 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800138 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800139 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800140 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
141 << "Should reject key events with undefined action.";
142
143 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100144 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800145 AKEY_EVENT_ACTION_MULTIPLE, 0,
146 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800147 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800148 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800149 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
150 << "Should reject key events with ACTION_MULTIPLE.";
151}
152
153TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
154 MotionEvent event;
155 PointerProperties pointerProperties[MAX_POINTERS + 1];
156 PointerCoords pointerCoords[MAX_POINTERS + 1];
157 for (int i = 0; i <= MAX_POINTERS; i++) {
158 pointerProperties[i].clear();
159 pointerProperties[i].id = i;
160 pointerCoords[i].clear();
161 }
162
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800163 // Some constants commonly used below
164 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
165 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
166 constexpr int32_t metaState = AMETA_NONE;
167 constexpr MotionClassification classification = MotionClassification::NONE;
168
Michael Wrightd02c5b62014-02-10 15:10:22 -0800169 // Rejects undefined motion actions.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800170 event.initialize(DEVICE_ID, source, DISPLAY_ID,
171 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
172 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800173 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800174 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800175 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
176 << "Should reject motion events with undefined action.";
177
178 // Rejects pointer down with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800179 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800181 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
182 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800183 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800184 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800185 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
186 << "Should reject motion events with pointer down index too large.";
187
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800188 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800189 AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800190 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
191 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800192 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800193 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800194 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
195 << "Should reject motion events with pointer down index too small.";
196
197 // Rejects pointer up with invalid index.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800198 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800199 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800200 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
201 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800202 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800203 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
205 << "Should reject motion events with pointer up index too large.";
206
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800207 event.initialize(DEVICE_ID, source, DISPLAY_ID,
Dan Albert8b10c652016-02-02 17:08:05 -0800208 AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800209 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
210 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800211 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800212 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
214 << "Should reject motion events with pointer up index too small.";
215
216 // Rejects motion events with invalid number of pointers.
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800217 event.initialize(DEVICE_ID, source, DISPLAY_ID,
218 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
219 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800220 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800221 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800222 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
223 << "Should reject motion events with 0 pointers.";
224
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800225 event.initialize(DEVICE_ID, source, DISPLAY_ID,
226 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800227 ARBITRARY_TIME, ARBITRARY_TIME,
228 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800229 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800230 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800231 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
232 << "Should reject motion events with more than MAX_POINTERS pointers.";
233
234 // Rejects motion events with invalid pointer ids.
235 pointerProperties[0].id = -1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800236 event.initialize(DEVICE_ID, source, DISPLAY_ID,
237 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
238 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800239 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800240 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800241 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
242 << "Should reject motion events with pointer ids less than 0.";
243
244 pointerProperties[0].id = MAX_POINTER_ID + 1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800245 event.initialize(DEVICE_ID, source, DISPLAY_ID,
246 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
247 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800248 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800249 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800250 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
251 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
252
253 // Rejects motion events with duplicate pointer ids.
254 pointerProperties[0].id = 1;
255 pointerProperties[1].id = 1;
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800256 event.initialize(DEVICE_ID, source, DISPLAY_ID,
257 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
258 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800259 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800260 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800261 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
262 << "Should reject motion events with duplicate pointer ids.";
263}
264
Arthur Hungb92218b2018-08-14 12:00:21 +0800265// --- InputDispatcherTest SetInputWindowTest ---
266static const int32_t INJECT_EVENT_TIMEOUT = 500;
267static const int32_t DISPATCHING_TIMEOUT = 100;
268
269class FakeApplicationHandle : public InputApplicationHandle {
270public:
271 FakeApplicationHandle() {}
272 virtual ~FakeApplicationHandle() {}
273
274 virtual bool updateInfo() {
275 if (!mInfo) {
276 mInfo = new InputApplicationInfo();
277 }
278 mInfo->dispatchingTimeout = DISPATCHING_TIMEOUT;
279 return true;
280 }
281};
282
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800283class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800284public:
Tiger Huang8664f8c2018-10-11 19:14:35 +0800285 void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
286 int32_t expectedFlags = 0) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800287 uint32_t consumeSeq;
288 InputEvent* event;
289 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
290 &consumeSeq, &event);
291
292 ASSERT_EQ(OK, status)
293 << mName.c_str() << ": consumer consume should return OK.";
294 ASSERT_TRUE(event != nullptr)
295 << mName.c_str() << ": consumer should have returned non-NULL event.";
296 ASSERT_EQ(expectedEventType, event->getType())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800297 << mName.c_str() << ": event type should match.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800298
299 ASSERT_EQ(expectedDisplayId, event->getDisplayId())
Tiger Huang8664f8c2018-10-11 19:14:35 +0800300 << mName.c_str() << ": event displayId should be the same as expected.";
301
302 int32_t flags;
303 switch (expectedEventType) {
304 case AINPUT_EVENT_TYPE_KEY: {
305 KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
306 flags = typedEvent->getFlags();
307 break;
308 }
309 case AINPUT_EVENT_TYPE_MOTION: {
310 MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
311 flags = typedEvent->getFlags();
312 break;
313 }
314 default: {
315 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
316 }
317 }
318 ASSERT_EQ(expectedFlags, flags)
319 << mName.c_str() << ": event flags should be the same as expected.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800320
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800321 status = mConsumer->sendFinishedSignal(consumeSeq, handled());
Arthur Hungb92218b2018-08-14 12:00:21 +0800322 ASSERT_EQ(OK, status)
323 << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
324 }
325
326 void assertNoEvents() {
327 uint32_t consumeSeq;
328 InputEvent* event;
329 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
330 &consumeSeq, &event);
331 ASSERT_NE(OK, status)
332 << mName.c_str()
333 << ": should not have received any events, so consume(..) should not return OK.";
334 }
335
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800336protected:
337 explicit FakeInputReceiver(const sp<InputDispatcher>& dispatcher,
338 const std::string name, int32_t displayId) :
339 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
340 InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
341 mConsumer = new InputConsumer(mClientChannel);
342 }
343
344 virtual ~FakeInputReceiver() {
345 }
346
347 // return true if the event has been handled.
348 virtual bool handled() {
349 return false;
350 }
351
Arthur Hungb92218b2018-08-14 12:00:21 +0800352 sp<InputDispatcher> mDispatcher;
353 sp<InputChannel> mServerChannel, mClientChannel;
Robert Carr5c8a0262018-10-03 16:30:44 -0700354 sp<IBinder> mToken;
Arthur Hungb92218b2018-08-14 12:00:21 +0800355 InputConsumer *mConsumer;
356 PreallocatedInputEventFactory mEventFactory;
357
358 std::string mName;
Arthur Hungb92218b2018-08-14 12:00:21 +0800359 int32_t mDisplayId;
360};
361
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800362class FakeWindowHandle : public InputWindowHandle, public FakeInputReceiver {
363public:
364 static const int32_t WIDTH = 600;
365 static const int32_t HEIGHT = 800;
366
367 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
368 const sp<InputDispatcher>& dispatcher, const std::string name, int32_t displayId) :
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800369 FakeInputReceiver(dispatcher, name, displayId),
370 mFocused(false) {
Robert Carr4e670e52018-08-15 13:26:12 -0700371 mServerChannel->setToken(new BBinder());
Robert Carr803535b2018-08-02 16:38:15 -0700372 mDispatcher->registerInputChannel(mServerChannel, displayId);
Robert Carr740167f2018-10-11 19:03:41 -0700373
374 inputApplicationHandle->updateInfo();
375 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800376 }
377
378 virtual bool updateInfo() {
Robert Carr5c8a0262018-10-03 16:30:44 -0700379 mInfo.token = mServerChannel->getToken();
Arthur Hung3b413f22018-10-26 18:05:34 +0800380 mInfo.name = mName;
381 mInfo.layoutParamsFlags = 0;
382 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
383 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
384 mInfo.frameLeft = 0;
385 mInfo.frameTop = 0;
386 mInfo.frameRight = WIDTH;
387 mInfo.frameBottom = HEIGHT;
Robert Carre07e1032018-11-26 12:55:53 -0800388 mInfo.globalScaleFactor = 1.0;
Arthur Hung3b413f22018-10-26 18:05:34 +0800389 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
390 mInfo.visible = true;
391 mInfo.canReceiveKeys = true;
392 mInfo.hasFocus = mFocused;
393 mInfo.hasWallpaper = false;
394 mInfo.paused = false;
395 mInfo.layer = 0;
396 mInfo.ownerPid = INJECTOR_PID;
397 mInfo.ownerUid = INJECTOR_UID;
398 mInfo.inputFeatures = 0;
399 mInfo.displayId = mDisplayId;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800400
401 return true;
402 }
403
404 void setFocus() {
405 mFocused = true;
406 }
407
408 void assertNoEvents() {
409 uint32_t consumeSeq;
410 InputEvent* event;
411 status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
412 &consumeSeq, &event);
413 ASSERT_NE(OK, status)
414 << mName.c_str()
415 << ": should not have received any events, so consume(..) should not return OK.";
416 }
417protected:
418 virtual bool handled() {
419 return true;
420 }
421
422 bool mFocused;
423};
424
Tiger Huang721e26f2018-07-24 22:26:19 +0800425static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
426 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800427 KeyEvent event;
428 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
429
430 // Define a valid key down event.
Tiger Huang721e26f2018-07-24 22:26:19 +0800431 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800432 AKEY_EVENT_ACTION_DOWN, /* flags */ 0,
433 AKEYCODE_A, KEY_A, AMETA_NONE, /* repeatCount */ 0, currentTime, currentTime);
434
435 // Inject event until dispatch out.
436 return dispatcher->injectInputEvent(
437 &event,
438 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
439 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
440}
441
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800442static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
443 int32_t displayId) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800444 MotionEvent event;
445 PointerProperties pointerProperties[1];
446 PointerCoords pointerCoords[1];
447
448 pointerProperties[0].clear();
449 pointerProperties[0].id = 0;
450 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
451
452 pointerCoords[0].clear();
453 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 100);
454 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 200);
455
456 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
457 // Define a valid motion down event.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800458 event.initialize(DEVICE_ID, source, displayId,
Arthur Hungb92218b2018-08-14 12:00:21 +0800459 AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800460 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
461 /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
Arthur Hungb92218b2018-08-14 12:00:21 +0800462 /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
463 pointerCoords);
464
465 // Inject event until dispatch out.
466 return dispatcher->injectInputEvent(
467 &event,
468 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
469 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
470}
471
472TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
473 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800474 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
475 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800476
477 Vector<sp<InputWindowHandle>> inputWindowHandles;
478 inputWindowHandles.add(window);
479
480 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800481 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
482 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800483 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
484
485 // Window should receive motion event.
486 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
487}
488
489// The foreground window should receive the first touch down event.
490TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
491 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800492 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
493 ADISPLAY_ID_DEFAULT);
494 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
495 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800496
497 Vector<sp<InputWindowHandle>> inputWindowHandles;
498 inputWindowHandles.add(windowTop);
499 inputWindowHandles.add(windowSecond);
500
501 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800502 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
503 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800504 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
505
506 // Top window should receive the touch down event. Second window should not receive anything.
507 windowTop->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
508 windowSecond->assertNoEvents();
509}
510
511TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
512 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800513 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
514 ADISPLAY_ID_DEFAULT);
515 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
516 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800517
518 // Set focus application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800519 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800520
521 // Expect one focus window exist in display.
522 windowSecond->setFocus();
523 Vector<sp<InputWindowHandle>> inputWindowHandles;
524 inputWindowHandles.add(windowTop);
525 inputWindowHandles.add(windowSecond);
526
527 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
528 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
529 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
530
531 // Focused window should receive event.
532 windowTop->assertNoEvents();
533 windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
534}
535
Arthur Hung3b413f22018-10-26 18:05:34 +0800536TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
537 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
538
539 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
540 ADISPLAY_ID_DEFAULT);
541 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
542 ADISPLAY_ID_DEFAULT);
543
544 windowTop->setFocus();
545
546 Vector<sp<InputWindowHandle>> inputWindowHandles;
547 inputWindowHandles.add(windowTop);
548 inputWindowHandles.add(windowSecond);
549
550 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
551
552 // Release channel for window is no longer valid.
553 windowTop->releaseChannel();
554
555 // Test inject a motion down, should timeout because of no target channel.
556 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
557 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
558
559 // Top window is invalid, so it should not receive any input event.
560 windowTop->assertNoEvents();
561 windowSecond->assertNoEvents();
562}
563
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800564/* Test InputDispatcher for MultiDisplay */
565class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
566public:
567 static constexpr int32_t SECOND_DISPLAY_ID = 1;
568 virtual void SetUp() {
569 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +0800570
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800571 application1 = new FakeApplicationHandle();
572 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
573 ADISPLAY_ID_DEFAULT);
574 Vector<sp<InputWindowHandle>> inputWindowHandles;
575 inputWindowHandles.push(windowInPrimary);
576 // Set focus window for primary display, but focused display would be second one.
577 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
578 windowInPrimary->setFocus();
579 mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800580
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800581 application2 = new FakeApplicationHandle();
582 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
583 SECOND_DISPLAY_ID);
584 // Set focus to second display window.
585 Vector<sp<InputWindowHandle>> inputWindowHandles_Second;
586 inputWindowHandles_Second.push(windowInSecondary);
587 // Set focus display to second one.
588 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
589 // Set focus window for second display.
590 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
591 windowInSecondary->setFocus();
592 mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
593 }
594
595 virtual void TearDown() {
596 InputDispatcherTest::TearDown();
597
598 application1.clear();
599 windowInPrimary.clear();
600 application2.clear();
601 windowInSecondary.clear();
602 }
603
604protected:
605 sp<FakeApplicationHandle> application1;
606 sp<FakeWindowHandle> windowInPrimary;
607 sp<FakeApplicationHandle> application2;
608 sp<FakeWindowHandle> windowInSecondary;
609};
610
611TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
612 // Test touch down on primary display.
613 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
614 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800615 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
616 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
617 windowInSecondary->assertNoEvents();
618
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800619 // Test touch down on second display.
620 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
621 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +0800622 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
623 windowInPrimary->assertNoEvents();
624 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
625}
626
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800627TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +0800628 // Test inject a key down with display id specified.
629 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
630 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
631 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_DEFAULT);
632 windowInSecondary->assertNoEvents();
633
634 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +0800635 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
636 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
637 windowInPrimary->assertNoEvents();
638 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
639
640 // Remove secondary display.
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800641 Vector<sp<InputWindowHandle>> noWindows;
642 mDispatcher->setInputWindows(noWindows, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +0800643
644 // Expect old focus should receive a cancel event.
Tiger Huang8664f8c2018-10-11 19:14:35 +0800645 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
646 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +0800647
648 // Test inject a key down, should timeout because of no target window.
649 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
650 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
651 windowInPrimary->assertNoEvents();
652 windowInSecondary->assertNoEvents();
653}
654
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800655class FakeMonitorReceiver : public FakeInputReceiver, public RefBase {
656public:
657 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
658 int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
Robert Carr803535b2018-08-02 16:38:15 -0700659 mDispatcher->registerInputChannel(mServerChannel, displayId);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800660 }
661};
662
663// Test per-display input monitors for motion event.
664TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
665 sp<FakeMonitorReceiver> monitorInPrimary =
666 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
667 sp<FakeMonitorReceiver> monitorInSecondary =
668 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
669
670 // Test touch down on primary display.
671 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
672 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
673 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
674 windowInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
675 monitorInPrimary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_DEFAULT);
676 windowInSecondary->assertNoEvents();
677 monitorInSecondary->assertNoEvents();
678
679 // Test touch down on second display.
680 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
681 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
682 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
683 windowInPrimary->assertNoEvents();
684 monitorInPrimary->assertNoEvents();
685 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
686 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, SECOND_DISPLAY_ID);
687
688 // Test inject a non-pointer motion event.
689 // If specific a display, it will dispatch to the focused window of particular display,
690 // or it will dispatch to the focused window of focused display.
691 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
692 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
693 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
694 windowInPrimary->assertNoEvents();
695 monitorInPrimary->assertNoEvents();
696 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
697 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, ADISPLAY_ID_NONE);
698}
699
700// Test per-display input monitors for key event.
701TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
702 //Input monitor per display.
703 sp<FakeMonitorReceiver> monitorInPrimary =
704 new FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
705 sp<FakeMonitorReceiver> monitorInSecondary =
706 new FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
707
708 // Test inject a key down.
709 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
710 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
711 windowInPrimary->assertNoEvents();
712 monitorInPrimary->assertNoEvents();
713 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
714 monitorInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
715}
716
Michael Wrightd02c5b62014-02-10 15:10:22 -0800717} // namespace android