blob: 2fb1b65d934fb6b04d006cc488c44707cf56ffbf [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
Robert Carr803535b2018-08-02 16:38:15 -070019#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080020#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070021
Michael Wrightd02c5b62014-02-10 15:10:22 -080022#include <gtest/gtest.h>
23#include <linux/input.h>
chaviwd1c23182019-12-20 18:44:56 -080024#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080025
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
chaviwd1c23182019-12-20 18:44:56 -080041struct PointF {
42 float x;
43 float y;
44};
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
Gang Wang342c9272020-01-13 13:15:04 -050046/**
47 * Return a DOWN key event with KEYCODE_A.
48 */
49static KeyEvent getTestKeyEvent() {
50 KeyEvent event;
51
52 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
53 AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
54 ARBITRARY_TIME);
55 return event;
56}
57
Michael Wrightd02c5b62014-02-10 15:10:22 -080058// --- FakeInputDispatcherPolicy ---
59
60class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
61 InputDispatcherConfiguration mConfig;
62
63protected:
64 virtual ~FakeInputDispatcherPolicy() {
65 }
66
67public:
68 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080069 }
70
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080071 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080072 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
73 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080074 }
75
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080076 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080077 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
78 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080079 }
80
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080081 void assertFilterInputEventWasNotCalled() { ASSERT_EQ(nullptr, mFilteredEvent); }
Michael Wrightd02c5b62014-02-10 15:10:22 -080082
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080083 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
84 ASSERT_TRUE(mConfigurationChangedTime)
85 << "Timed out waiting for configuration changed call";
86 ASSERT_EQ(*mConfigurationChangedTime, when);
87 mConfigurationChangedTime = std::nullopt;
88 }
89
90 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
91 ASSERT_TRUE(mLastNotifySwitch);
92 // We do not check sequenceNum because it is not exposed to the policy
93 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
94 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
95 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
96 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
97 mLastNotifySwitch = std::nullopt;
98 }
99
chaviwfd6d3512019-03-25 13:23:49 -0700100 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800101 ASSERT_EQ(touchedToken, mOnPointerDownToken);
102 mOnPointerDownToken.clear();
103 }
104
105 void assertOnPointerDownWasNotCalled() {
106 ASSERT_TRUE(mOnPointerDownToken == nullptr)
107 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700108 }
109
Michael Wrightd02c5b62014-02-10 15:10:22 -0800110private:
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800111 std::unique_ptr<InputEvent> mFilteredEvent;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800112 std::optional<nsecs_t> mConfigurationChangedTime;
chaviwfd6d3512019-03-25 13:23:49 -0700113 sp<IBinder> mOnPointerDownToken;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800114 std::optional<NotifySwitchArgs> mLastNotifySwitch;
Jackal Guof9696682018-10-05 12:23:23 +0800115
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800116 virtual void notifyConfigurationChanged(nsecs_t when) override {
117 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800118 }
119
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100120 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -0700121 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800122 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800123 return 0;
124 }
125
Robert Carr803535b2018-08-02 16:38:15 -0700126 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800127 }
128
chaviw0c06c6e2019-01-09 13:27:07 -0800129 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700130 }
131
Michael Wrightd02c5b62014-02-10 15:10:22 -0800132 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
133 *outConfig = mConfig;
134 }
135
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800136 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Jackal Guof9696682018-10-05 12:23:23 +0800137 switch (inputEvent->getType()) {
138 case AINPUT_EVENT_TYPE_KEY: {
139 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800140 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800141 break;
142 }
143
144 case AINPUT_EVENT_TYPE_MOTION: {
145 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800146 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800147 break;
148 }
149 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800150 return true;
151 }
152
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100153 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154 }
155
Charles Chen3611f1f2019-01-29 17:26:18 +0800156 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157 }
158
Robert Carr803535b2018-08-02 16:38:15 -0700159 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100160 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800161 return 0;
162 }
163
Robert Carr803535b2018-08-02 16:38:15 -0700164 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100165 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800166 return false;
167 }
168
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800169 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
170 uint32_t policyFlags) override {
171 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
172 * essentially a passthrough for notifySwitch.
173 */
174 mLastNotifySwitch =
175 NotifySwitchArgs(1 /*sequenceNum*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176 }
177
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100178 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800179 }
180
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100181 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800182 return false;
183 }
Jackal Guof9696682018-10-05 12:23:23 +0800184
chaviwfd6d3512019-03-25 13:23:49 -0700185 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
186 mOnPointerDownToken = newToken;
187 }
188
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800189 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
190 int32_t displayId) {
191 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
192 ASSERT_EQ(mFilteredEvent->getType(), type);
193
194 if (type == AINPUT_EVENT_TYPE_KEY) {
195 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
196 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
197 EXPECT_EQ(keyEvent.getAction(), action);
198 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
199 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
200 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
201 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
202 EXPECT_EQ(motionEvent.getAction(), action);
203 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
204 } else {
205 FAIL() << "Unknown type: " << type;
206 }
207
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800208 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800209 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800210};
211
Gang Wang342c9272020-01-13 13:15:04 -0500212// --- HmacKeyManagerTest ---
213
214class HmacKeyManagerTest : public testing::Test {
215protected:
216 HmacKeyManager mHmacKeyManager;
217};
218
219/**
220 * Ensure that separate calls to sign the same data are generating the same key.
221 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
222 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
223 * tests.
224 */
225TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
226 KeyEvent event = getTestKeyEvent();
227 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
228
229 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
230 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
231 ASSERT_EQ(hmac1, hmac2);
232}
233
234/**
235 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
236 */
237TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
238 KeyEvent event = getTestKeyEvent();
239 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
240 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
241
242 verifiedEvent.deviceId += 1;
243 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
244
245 verifiedEvent.source += 1;
246 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
247
248 verifiedEvent.eventTimeNanos += 1;
249 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
250
251 verifiedEvent.displayId += 1;
252 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
253
254 verifiedEvent.action += 1;
255 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
256
257 verifiedEvent.downTimeNanos += 1;
258 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
259
260 verifiedEvent.flags += 1;
261 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
262
263 verifiedEvent.keyCode += 1;
264 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
265
266 verifiedEvent.scanCode += 1;
267 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
268
269 verifiedEvent.metaState += 1;
270 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
271
272 verifiedEvent.repeatCount += 1;
273 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
274}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800275
276// --- InputDispatcherTest ---
277
278class InputDispatcherTest : public testing::Test {
279protected:
280 sp<FakeInputDispatcherPolicy> mFakePolicy;
281 sp<InputDispatcher> mDispatcher;
282
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700283 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800284 mFakePolicy = new FakeInputDispatcherPolicy();
285 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800286 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
287 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700288 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800289 }
290
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700291 virtual void TearDown() override {
292 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800293 mFakePolicy.clear();
294 mDispatcher.clear();
295 }
296};
297
298
299TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
300 KeyEvent event;
301
302 // Rejects undefined key actions.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600303 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
304 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
305 ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800306 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800307 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800308 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
309 << "Should reject key events with undefined action.";
310
311 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600312 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
313 AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
314 ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800315 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800316 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800317 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
318 << "Should reject key events with ACTION_MULTIPLE.";
319}
320
321TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
322 MotionEvent event;
323 PointerProperties pointerProperties[MAX_POINTERS + 1];
324 PointerCoords pointerCoords[MAX_POINTERS + 1];
325 for (int i = 0; i <= MAX_POINTERS; i++) {
326 pointerProperties[i].clear();
327 pointerProperties[i].id = i;
328 pointerCoords[i].clear();
329 }
330
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800331 // Some constants commonly used below
332 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
333 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
334 constexpr int32_t metaState = AMETA_NONE;
335 constexpr MotionClassification classification = MotionClassification::NONE;
336
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 // Rejects undefined motion actions.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600338 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
339 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
340 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
341 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700342 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800343 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800344 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800345 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
346 << "Should reject motion events with undefined action.";
347
348 // Rejects pointer down with invalid index.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600349 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700350 AMOTION_EVENT_ACTION_POINTER_DOWN |
351 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600352 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
353 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
354 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700355 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800356 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800357 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800358 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
359 << "Should reject motion events with pointer down index too large.";
360
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600361 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700362 AMOTION_EVENT_ACTION_POINTER_DOWN |
363 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600364 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
365 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
366 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700367 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800368 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800369 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800370 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
371 << "Should reject motion events with pointer down index too small.";
372
373 // Rejects pointer up with invalid index.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600374 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700375 AMOTION_EVENT_ACTION_POINTER_UP |
376 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600377 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
378 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
379 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700380 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800381 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800382 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800383 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
384 << "Should reject motion events with pointer up index too large.";
385
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600386 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700387 AMOTION_EVENT_ACTION_POINTER_UP |
388 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600389 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
390 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
391 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700392 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800393 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800394 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800395 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
396 << "Should reject motion events with pointer up index too small.";
397
398 // Rejects motion events with invalid number of pointers.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600399 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
400 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
401 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
402 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700403 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800404 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800405 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800406 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
407 << "Should reject motion events with 0 pointers.";
408
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600409 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
410 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
411 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
412 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700413 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800414 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800415 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800416 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
417 << "Should reject motion events with more than MAX_POINTERS pointers.";
418
419 // Rejects motion events with invalid pointer ids.
420 pointerProperties[0].id = -1;
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600421 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
422 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
423 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
424 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700425 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800426 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800427 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800428 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
429 << "Should reject motion events with pointer ids less than 0.";
430
431 pointerProperties[0].id = MAX_POINTER_ID + 1;
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600432 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
433 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
434 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
435 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700436 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800437 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800438 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800439 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
440 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
441
442 // Rejects motion events with duplicate pointer ids.
443 pointerProperties[0].id = 1;
444 pointerProperties[1].id = 1;
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600445 event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
446 edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
447 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
448 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700449 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800450 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800451 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800452 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
453 << "Should reject motion events with duplicate pointer ids.";
454}
455
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800456/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
457
458TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
459 constexpr nsecs_t eventTime = 20;
460 NotifyConfigurationChangedArgs args(10 /*sequenceNum*/, eventTime);
461 mDispatcher->notifyConfigurationChanged(&args);
462 ASSERT_TRUE(mDispatcher->waitForIdle());
463
464 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
465}
466
467TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
468 NotifySwitchArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, 0 /*policyFlags*/,
469 1 /*switchValues*/, 2 /*switchMask*/);
470 mDispatcher->notifySwitch(&args);
471
472 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
473 args.policyFlags |= POLICY_FLAG_TRUSTED;
474 mFakePolicy->assertNotifySwitchWasCalled(args);
475}
476
Arthur Hungb92218b2018-08-14 12:00:21 +0800477// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800478static constexpr int32_t INJECT_EVENT_TIMEOUT = 500;
479static constexpr int32_t DISPATCHING_TIMEOUT = 100;
Arthur Hungb92218b2018-08-14 12:00:21 +0800480
481class FakeApplicationHandle : public InputApplicationHandle {
482public:
483 FakeApplicationHandle() {}
484 virtual ~FakeApplicationHandle() {}
485
486 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800487 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800488 return true;
489 }
490};
491
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800492class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800493public:
chaviwd1c23182019-12-20 18:44:56 -0800494 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
495 : mName(name) {
496 mConsumer = std::make_unique<InputConsumer>(clientChannel);
497 }
498
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800499 InputEvent* consume() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800500 uint32_t consumeSeq;
501 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800502
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800503 std::chrono::time_point start = std::chrono::steady_clock::now();
504 status_t status = WOULD_BLOCK;
505 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800506 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800507 &event);
508 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
509 if (elapsed > 100ms) {
510 break;
511 }
512 }
513
514 if (status == WOULD_BLOCK) {
515 // Just means there's no event available.
516 return nullptr;
517 }
518
519 if (status != OK) {
520 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
521 return nullptr;
522 }
523 if (event == nullptr) {
524 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
525 return nullptr;
526 }
527
chaviwd1c23182019-12-20 18:44:56 -0800528 status = mConsumer->sendFinishedSignal(consumeSeq, true);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800529 if (status != OK) {
530 ADD_FAILURE() << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
531 }
532 return event;
533 }
534
535 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
536 int32_t expectedFlags) {
537 InputEvent* event = consume();
538
539 ASSERT_NE(nullptr, event) << mName.c_str()
540 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800541 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800542 << mName.c_str() << "expected " << inputEventTypeToString(expectedEventType)
543 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800544
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800545 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800546
Tiger Huang8664f8c2018-10-11 19:14:35 +0800547 switch (expectedEventType) {
548 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800549 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
550 EXPECT_EQ(expectedAction, keyEvent.getAction());
551 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800552 break;
553 }
554 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800555 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
556 EXPECT_EQ(expectedAction, motionEvent.getAction());
557 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800558 break;
559 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100560 case AINPUT_EVENT_TYPE_FOCUS: {
561 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
562 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800563 default: {
564 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
565 }
566 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800567 }
568
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100569 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
570 InputEvent* event = consume();
571 ASSERT_NE(nullptr, event) << mName.c_str()
572 << ": consumer should have returned non-NULL event.";
573 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
574 << "Got " << inputEventTypeToString(event->getType())
575 << " event instead of FOCUS event";
576
577 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
578 << mName.c_str() << ": event displayId should always be NONE.";
579
580 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
581 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
582 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
583 }
584
chaviwd1c23182019-12-20 18:44:56 -0800585 void assertNoEvents() {
586 InputEvent* event = consume();
587 ASSERT_EQ(nullptr, event)
588 << mName.c_str()
589 << ": should not have received any events, so consume() should return NULL";
590 }
591
592 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
593
594protected:
595 std::unique_ptr<InputConsumer> mConsumer;
596 PreallocatedInputEventFactory mEventFactory;
597
598 std::string mName;
599};
600
601class FakeWindowHandle : public InputWindowHandle {
602public:
603 static const int32_t WIDTH = 600;
604 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800605
606 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
607 const sp<InputDispatcher>& dispatcher, const std::string name,
608 int32_t displayId, sp<IBinder> token = nullptr)
609 : mName(name) {
610 if (token == nullptr) {
611 sp<InputChannel> serverChannel, clientChannel;
612 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
613 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
614 dispatcher->registerInputChannel(serverChannel);
615 token = serverChannel->getConnectionToken();
616 }
617
618 inputApplicationHandle->updateInfo();
619 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
620
621 mInfo.token = token;
chaviwaf87b3e2019-10-01 16:59:28 -0700622 mInfo.id = 0;
chaviwd1c23182019-12-20 18:44:56 -0800623 mInfo.name = name;
624 mInfo.layoutParamsFlags = 0;
625 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
626 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
627 mInfo.frameLeft = 0;
628 mInfo.frameTop = 0;
629 mInfo.frameRight = WIDTH;
630 mInfo.frameBottom = HEIGHT;
631 mInfo.globalScaleFactor = 1.0;
632 mInfo.touchableRegion.clear();
633 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
634 mInfo.visible = true;
635 mInfo.canReceiveKeys = true;
636 mInfo.hasFocus = false;
637 mInfo.hasWallpaper = false;
638 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800639 mInfo.ownerPid = INJECTOR_PID;
640 mInfo.ownerUid = INJECTOR_UID;
641 mInfo.inputFeatures = 0;
642 mInfo.displayId = displayId;
643 }
644
645 virtual bool updateInfo() { return true; }
646
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100647 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800648
649 void setFrame(const Rect& frame) {
650 mInfo.frameLeft = frame.left;
651 mInfo.frameTop = frame.top;
652 mInfo.frameRight = frame.right;
653 mInfo.frameBottom = frame.bottom;
654 mInfo.touchableRegion.clear();
655 mInfo.addTouchableRegion(frame);
656 }
657
658 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
659
chaviwaf87b3e2019-10-01 16:59:28 -0700660 void setId(int32_t id) { mInfo.id = id; }
661
662 void setWindowScale(float xScale, float yScale) {
663 mInfo.windowXScale = xScale;
664 mInfo.windowYScale = yScale;
665 }
666
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800667 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
668 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
669 expectedFlags);
670 }
671
Svet Ganov5d3bc372020-01-26 23:11:07 -0800672 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
673 int32_t expectedFlags = 0) {
674 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
675 expectedFlags);
676 }
677
678 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
679 int32_t expectedFlags = 0) {
680 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
681 expectedFlags);
682 }
683
684 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
685 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800686 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
687 expectedFlags);
688 }
689
Svet Ganov5d3bc372020-01-26 23:11:07 -0800690 void consumeMotionPointerDown(int32_t pointerIdx,
691 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
692 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
693 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
694 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
695 }
696
697 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
698 int32_t expectedFlags = 0) {
699 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
700 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
701 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
702 }
703
704 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
705 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000706 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
707 expectedFlags);
708 }
709
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100710 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
711 ASSERT_NE(mInputReceiver, nullptr)
712 << "Cannot consume events from a window with no receiver";
713 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
714 }
715
chaviwd1c23182019-12-20 18:44:56 -0800716 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
717 int32_t expectedFlags) {
718 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
719 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
720 expectedFlags);
721 }
722
chaviwaf87b3e2019-10-01 16:59:28 -0700723 InputEvent* consume() {
724 if (mInputReceiver == nullptr) {
725 return nullptr;
726 }
727 return mInputReceiver->consume();
728 }
729
Arthur Hungb92218b2018-08-14 12:00:21 +0800730 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800731 ASSERT_NE(mInputReceiver, nullptr)
732 << "Call 'assertNoEvents' on a window with an InputReceiver";
733 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800734 }
735
chaviwaf87b3e2019-10-01 16:59:28 -0700736 sp<IBinder> getToken() { return mInfo.token; }
737
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100738 const std::string& getName() { return mName; }
739
chaviwd1c23182019-12-20 18:44:56 -0800740private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100741 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800742 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800743};
744
Tiger Huang721e26f2018-07-24 22:26:19 +0800745static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
746 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800747 KeyEvent event;
748 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
749
750 // Define a valid key down event.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600751 event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, INVALID_HMAC,
752 AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
753 /* repeatCount */ 0, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800754
755 // Inject event until dispatch out.
756 return dispatcher->injectInputEvent(
757 &event,
758 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
759 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
760}
761
Garfield Tan00f511d2019-06-12 16:55:40 -0700762static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
763 int32_t source, int32_t displayId, int32_t x, int32_t y,
764 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
765 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800766 MotionEvent event;
767 PointerProperties pointerProperties[1];
768 PointerCoords pointerCoords[1];
769
770 pointerProperties[0].clear();
771 pointerProperties[0].id = 0;
772 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
773
774 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700775 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
776 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800777
778 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
779 // Define a valid motion down event.
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600780 event.initialize(DEVICE_ID, source, displayId, INVALID_HMAC, action, /* actionButton */ 0,
781 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700782 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600783 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
784 /* xPrecision */ 0, /* yPrecision */ 0, xCursorPosition, yCursorPosition,
785 currentTime, currentTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700786 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800787
788 // Inject event until dispatch out.
789 return dispatcher->injectInputEvent(
790 &event,
791 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
792 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
793}
794
Garfield Tan00f511d2019-06-12 16:55:40 -0700795static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
796 int32_t displayId, int32_t x = 100, int32_t y = 200) {
797 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
798}
799
Michael Wright3a240c42019-12-10 20:53:41 +0000800static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
801 int32_t displayId, int32_t x = 100, int32_t y = 200) {
802 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y);
803}
804
Jackal Guof9696682018-10-05 12:23:23 +0800805static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
806 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
807 // Define a valid key event.
808 NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
809 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
810 AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
811
812 return args;
813}
814
chaviwd1c23182019-12-20 18:44:56 -0800815static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
816 const std::vector<PointF>& points) {
817 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700818 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
819 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
820 }
821
chaviwd1c23182019-12-20 18:44:56 -0800822 PointerProperties pointerProperties[pointerCount];
823 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800824
chaviwd1c23182019-12-20 18:44:56 -0800825 for (size_t i = 0; i < pointerCount; i++) {
826 pointerProperties[i].clear();
827 pointerProperties[i].id = i;
828 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800829
chaviwd1c23182019-12-20 18:44:56 -0800830 pointerCoords[i].clear();
831 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
832 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
833 }
Jackal Guof9696682018-10-05 12:23:23 +0800834
835 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
836 // Define a valid motion event.
837 NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700838 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
839 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800840 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
841 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700842 AMOTION_EVENT_INVALID_CURSOR_POSITION,
843 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800844
845 return args;
846}
847
chaviwd1c23182019-12-20 18:44:56 -0800848static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
849 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
850}
851
Arthur Hungb92218b2018-08-14 12:00:21 +0800852TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
853 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800854 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
855 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800856
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800857 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800858 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
859 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800860 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
861
862 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800863 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800864}
865
866// The foreground window should receive the first touch down event.
867TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
868 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800869 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
870 ADISPLAY_ID_DEFAULT);
871 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
872 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800873
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800874 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800875 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
876 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800877 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
878
879 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800880 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800881 windowSecond->assertNoEvents();
882}
883
884TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
885 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800886 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
887 ADISPLAY_ID_DEFAULT);
888 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
889 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800890
Arthur Hung7ab76b12019-01-09 19:17:20 +0800891 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800892 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800893
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100894 // Display should have only one focused window
895 windowSecond->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800896 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100897
898 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +0800899 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
900 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
901
902 // Focused window should receive event.
903 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800904 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +0800905}
906
Arthur Hung7ab76b12019-01-09 19:17:20 +0800907TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
908 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
909 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
910 ADISPLAY_ID_DEFAULT);
911 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
912 ADISPLAY_ID_DEFAULT);
913
914 // Set focused application.
915 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
916
917 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100918 windowTop->setFocus(true);
919 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800920
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800921 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100922 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800923 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
924 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
925
926 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800927 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800928 windowSecond->assertNoEvents();
929}
930
Arthur Hung3b413f22018-10-26 18:05:34 +0800931TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
932 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
933
934 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
935 ADISPLAY_ID_DEFAULT);
936 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
937 ADISPLAY_ID_DEFAULT);
938
Arthur Hung832bc4a2019-01-28 11:43:17 +0800939 // Set focused application.
940 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +0800941
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100942 windowTop->setFocus(true);
943 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +0800944 // Release channel for window is no longer valid.
945 windowTop->releaseChannel();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800946 mDispatcher->setInputWindows({windowTop, windowSecond}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100947 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +0800948
Arthur Hung832bc4a2019-01-28 11:43:17 +0800949 // Test inject a key down, should dispatch to a valid window.
950 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
951 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +0800952
953 // Top window is invalid, so it should not receive any input event.
954 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800955 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +0800956}
957
Garfield Tan00f511d2019-06-12 16:55:40 -0700958TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
959 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
960
961 sp<FakeWindowHandle> windowLeft =
962 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
963 windowLeft->setFrame(Rect(0, 0, 600, 800));
964 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
965 sp<FakeWindowHandle> windowRight =
966 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
967 windowRight->setFrame(Rect(600, 0, 1200, 800));
968 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
969
970 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
971
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -0800972 mDispatcher->setInputWindows({windowLeft, windowRight}, ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700973
974 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
975 // left window. This event should be dispatched to the left window.
976 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
977 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
978 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800979 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -0700980 windowRight->assertNoEvents();
981}
982
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800983TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
984 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
985 sp<FakeWindowHandle> window =
986 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100987 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800988
989 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100990 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800991
992 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
993 mDispatcher->notifyKey(&keyArgs);
994
995 // Window should receive key down event.
996 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
997
998 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
999 // on the app side.
1000 NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
1001 mDispatcher->notifyDeviceReset(&args);
1002 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1003 AKEY_EVENT_FLAG_CANCELED);
1004}
1005
1006TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1007 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1008 sp<FakeWindowHandle> window =
1009 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1010
1011 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1012
1013 NotifyMotionArgs motionArgs =
1014 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1015 ADISPLAY_ID_DEFAULT);
1016 mDispatcher->notifyMotion(&motionArgs);
1017
1018 // Window should receive motion down event.
1019 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1020
1021 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1022 // on the app side.
1023 NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
1024 mDispatcher->notifyDeviceReset(&args);
1025 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1026 0 /*expectedFlags*/);
1027}
1028
Svet Ganov5d3bc372020-01-26 23:11:07 -08001029TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1030 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1031
1032 // Create a couple of windows
1033 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1034 "First Window", ADISPLAY_ID_DEFAULT);
1035 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1036 "Second Window", ADISPLAY_ID_DEFAULT);
1037
1038 // Add the windows to the dispatcher
1039 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1040
1041 // Send down to the first window
1042 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1043 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1044 mDispatcher->notifyMotion(&downMotionArgs);
1045 // Only the first window should get the down event
1046 firstWindow->consumeMotionDown();
1047 secondWindow->assertNoEvents();
1048
1049 // Transfer touch focus to the second window
1050 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1051 // The first window gets cancel and the second gets down
1052 firstWindow->consumeMotionCancel();
1053 secondWindow->consumeMotionDown();
1054
1055 // Send up event to the second window
1056 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1057 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1058 mDispatcher->notifyMotion(&upMotionArgs);
1059 // The first window gets no events and the second gets up
1060 firstWindow->assertNoEvents();
1061 secondWindow->consumeMotionUp();
1062}
1063
1064TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1065 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1066
1067 PointF touchPoint = {10, 10};
1068
1069 // Create a couple of windows
1070 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1071 "First Window", ADISPLAY_ID_DEFAULT);
1072 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1073 "Second Window", ADISPLAY_ID_DEFAULT);
1074
1075 // Add the windows to the dispatcher
1076 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1077
1078 // Send down to the first window
1079 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1080 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1081 mDispatcher->notifyMotion(&downMotionArgs);
1082 // Only the first window should get the down event
1083 firstWindow->consumeMotionDown();
1084 secondWindow->assertNoEvents();
1085
1086 // Send pointer down to the first window
1087 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1088 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1089 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1090 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1091 // Only the first window should get the pointer down event
1092 firstWindow->consumeMotionPointerDown(1);
1093 secondWindow->assertNoEvents();
1094
1095 // Transfer touch focus to the second window
1096 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1097 // The first window gets cancel and the second gets down and pointer down
1098 firstWindow->consumeMotionCancel();
1099 secondWindow->consumeMotionDown();
1100 secondWindow->consumeMotionPointerDown(1);
1101
1102 // Send pointer up to the second window
1103 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1104 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1105 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1106 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1107 // The first window gets nothing and the second gets pointer up
1108 firstWindow->assertNoEvents();
1109 secondWindow->consumeMotionPointerUp(1);
1110
1111 // Send up event to the second window
1112 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1113 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1114 mDispatcher->notifyMotion(&upMotionArgs);
1115 // The first window gets nothing and the second gets up
1116 firstWindow->assertNoEvents();
1117 secondWindow->consumeMotionUp();
1118}
1119
1120TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1121 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1122
1123 // Create a non touch modal window that supports split touch
1124 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1125 "First Window", ADISPLAY_ID_DEFAULT);
1126 firstWindow->setFrame(Rect(0, 0, 600, 400));
1127 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1128 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1129
1130 // Create a non touch modal window that supports split touch
1131 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1132 "Second Window", ADISPLAY_ID_DEFAULT);
1133 secondWindow->setFrame(Rect(0, 400, 600, 800));
1134 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1135 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1136
1137 // Add the windows to the dispatcher
1138 mDispatcher->setInputWindows({firstWindow, secondWindow}, ADISPLAY_ID_DEFAULT);
1139
1140 PointF pointInFirst = {300, 200};
1141 PointF pointInSecond = {300, 600};
1142
1143 // Send down to the first window
1144 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1145 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1146 mDispatcher->notifyMotion(&firstDownMotionArgs);
1147 // Only the first window should get the down event
1148 firstWindow->consumeMotionDown();
1149 secondWindow->assertNoEvents();
1150
1151 // Send down to the second window
1152 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1153 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1154 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1155 mDispatcher->notifyMotion(&secondDownMotionArgs);
1156 // The first window gets a move and the second a down
1157 firstWindow->consumeMotionMove();
1158 secondWindow->consumeMotionDown();
1159
1160 // Transfer touch focus to the second window
1161 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1162 // The first window gets cancel and the new gets pointer down (it already saw down)
1163 firstWindow->consumeMotionCancel();
1164 secondWindow->consumeMotionPointerDown(1);
1165
1166 // Send pointer up to the second window
1167 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1168 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1169 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1170 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1171 // The first window gets nothing and the second gets pointer up
1172 firstWindow->assertNoEvents();
1173 secondWindow->consumeMotionPointerUp(1);
1174
1175 // Send up event to the second window
1176 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1177 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1178 mDispatcher->notifyMotion(&upMotionArgs);
1179 // The first window gets nothing and the second gets up
1180 firstWindow->assertNoEvents();
1181 secondWindow->consumeMotionUp();
1182}
1183
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001184TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1185 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1186 sp<FakeWindowHandle> window =
1187 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1188
1189 window->setFocus(true);
1190 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1191
1192 window->consumeFocusEvent(true);
1193
1194 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1195 mDispatcher->notifyKey(&keyArgs);
1196
1197 // Window should receive key down event.
1198 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1199}
1200
1201TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1202 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1203 sp<FakeWindowHandle> window =
1204 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1205
1206 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1207
1208 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1209 mDispatcher->notifyKey(&keyArgs);
1210 mDispatcher->waitForIdle();
1211
1212 window->assertNoEvents();
1213}
1214
1215// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1216TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1217 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1218 sp<FakeWindowHandle> window =
1219 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1220
1221 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1222
1223 // Send key
1224 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1225 mDispatcher->notifyKey(&keyArgs);
1226 // Send motion
1227 NotifyMotionArgs motionArgs =
1228 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1229 ADISPLAY_ID_DEFAULT);
1230 mDispatcher->notifyMotion(&motionArgs);
1231
1232 // Window should receive only the motion event
1233 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1234 window->assertNoEvents(); // Key event or focus event will not be received
1235}
1236
chaviwd1c23182019-12-20 18:44:56 -08001237class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001238public:
1239 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001240 int32_t displayId, bool isGestureMonitor = false) {
1241 sp<InputChannel> serverChannel, clientChannel;
1242 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1243 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1244 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001245 }
1246
chaviwd1c23182019-12-20 18:44:56 -08001247 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1248
1249 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1250 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1251 expectedDisplayId, expectedFlags);
1252 }
1253
1254 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1255 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1256 expectedDisplayId, expectedFlags);
1257 }
1258
1259 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1260 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1261 expectedDisplayId, expectedFlags);
1262 }
1263
1264 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1265
1266private:
1267 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001268};
1269
1270// Tests for gesture monitors
1271TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1272 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1273 sp<FakeWindowHandle> window =
1274 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1275 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1276
chaviwd1c23182019-12-20 18:44:56 -08001277 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1278 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001279
1280 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1281 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1282 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1283 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001284 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001285}
1286
1287TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1288 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1289 sp<FakeWindowHandle> window =
1290 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1291
1292 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001293 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001294
1295 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001296 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001297
chaviwd1c23182019-12-20 18:44:56 -08001298 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1299 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001300
1301 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1302 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1303 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001304 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001305}
1306
1307TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1308 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1309 sp<FakeWindowHandle> window =
1310 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1311 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1312
chaviwd1c23182019-12-20 18:44:56 -08001313 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1314 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001315
1316 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1317 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1318 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1319 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001320 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001321
1322 window->releaseChannel();
1323
chaviwd1c23182019-12-20 18:44:56 -08001324 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001325
1326 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1327 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1328 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001329 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001330}
1331
chaviw81e2bb92019-12-18 15:03:51 -08001332TEST_F(InputDispatcherTest, TestMoveEvent) {
1333 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1334 sp<FakeWindowHandle> window =
1335 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1336
1337 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1338
1339 NotifyMotionArgs motionArgs =
1340 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1341 ADISPLAY_ID_DEFAULT);
1342
1343 mDispatcher->notifyMotion(&motionArgs);
1344 // Window should receive motion down event.
1345 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1346
1347 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
1348 motionArgs.sequenceNum += 1;
1349 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1350 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1351 motionArgs.pointerCoords[0].getX() - 10);
1352
1353 mDispatcher->notifyMotion(&motionArgs);
1354 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1355 0 /*expectedFlags*/);
1356}
1357
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001358/**
1359 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1360 * the device default right away. In the test scenario, we check both the default value,
1361 * and the action of enabling / disabling.
1362 */
1363TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1364 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1365 sp<FakeWindowHandle> window =
1366 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1367
1368 // Set focused application.
1369 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1370 window->setFocus(true);
1371
1372 SCOPED_TRACE("Check default value of touch mode");
1373 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1374 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1375
1376 SCOPED_TRACE("Remove the window to trigger focus loss");
1377 window->setFocus(false);
1378 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1379 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1380
1381 SCOPED_TRACE("Disable touch mode");
1382 mDispatcher->setInTouchMode(false);
1383 window->setFocus(true);
1384 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1385 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1386
1387 SCOPED_TRACE("Remove the window to trigger focus loss");
1388 window->setFocus(false);
1389 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1390 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1391
1392 SCOPED_TRACE("Enable touch mode again");
1393 mDispatcher->setInTouchMode(true);
1394 window->setFocus(true);
1395 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1396 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1397
1398 window->assertNoEvents();
1399}
1400
Gang Wange9087892020-01-07 12:17:14 -05001401TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1402 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1403 sp<FakeWindowHandle> window =
1404 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1405
1406 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1407 window->setFocus(true);
1408
1409 mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
1410 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1411
1412 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1413 mDispatcher->notifyKey(&keyArgs);
1414
1415 InputEvent* event = window->consume();
1416 ASSERT_NE(event, nullptr);
1417
1418 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1419 ASSERT_NE(verified, nullptr);
1420 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1421
1422 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1423 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1424 ASSERT_EQ(keyArgs.source, verified->source);
1425 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1426
1427 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1428
1429 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1430 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
1431 ASSERT_EQ(keyArgs.eventTime, verifiedKey.eventTimeNanos);
1432 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1433 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1434 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1435 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1436 ASSERT_EQ(0, verifiedKey.repeatCount);
1437}
1438
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001439/* Test InputDispatcher for MultiDisplay */
1440class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1441public:
1442 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001443 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001444 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001445
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001446 application1 = new FakeApplicationHandle();
1447 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1448 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001449
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001450 // Set focus window for primary display, but focused display would be second one.
1451 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001452 windowInPrimary->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001453 mDispatcher->setInputWindows({windowInPrimary}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001454 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001455
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001456 application2 = new FakeApplicationHandle();
1457 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1458 SECOND_DISPLAY_ID);
1459 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001460 // Set focus display to second one.
1461 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1462 // Set focus window for second display.
1463 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001464 windowInSecondary->setFocus(true);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001465 mDispatcher->setInputWindows({windowInSecondary}, SECOND_DISPLAY_ID);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001466 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001467 }
1468
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001469 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001470 InputDispatcherTest::TearDown();
1471
1472 application1.clear();
1473 windowInPrimary.clear();
1474 application2.clear();
1475 windowInSecondary.clear();
1476 }
1477
1478protected:
1479 sp<FakeApplicationHandle> application1;
1480 sp<FakeWindowHandle> windowInPrimary;
1481 sp<FakeApplicationHandle> application2;
1482 sp<FakeWindowHandle> windowInSecondary;
1483};
1484
1485TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1486 // Test touch down on primary display.
1487 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1488 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001489 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001490 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001491 windowInSecondary->assertNoEvents();
1492
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001493 // Test touch down on second display.
1494 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1495 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001496 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1497 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001498 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001499}
1500
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001501TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001502 // Test inject a key down with display id specified.
1503 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1504 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001505 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001506 windowInSecondary->assertNoEvents();
1507
1508 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001509 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1510 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1511 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001512 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001513
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001514 // Remove all windows in secondary display.
1515 mDispatcher->setInputWindows({}, SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001516
1517 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001518 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1519 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001520
1521 // Test inject a key down, should timeout because of no target window.
1522 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1523 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1524 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001525 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001526 windowInSecondary->assertNoEvents();
1527}
1528
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001529// Test per-display input monitors for motion event.
1530TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001531 FakeMonitorReceiver monitorInPrimary =
1532 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1533 FakeMonitorReceiver monitorInSecondary =
1534 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001535
1536 // Test touch down on primary display.
1537 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1538 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1539 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001540 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001541 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001542 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001543 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001544
1545 // Test touch down on second display.
1546 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1547 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1548 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1549 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001550 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001551 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001552 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001553
1554 // Test inject a non-pointer motion event.
1555 // If specific a display, it will dispatch to the focused window of particular display,
1556 // or it will dispatch to the focused window of focused display.
1557 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1558 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1559 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1560 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001561 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001562 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001563 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001564}
1565
1566// Test per-display input monitors for key event.
1567TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1568 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001569 FakeMonitorReceiver monitorInPrimary =
1570 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1571 FakeMonitorReceiver monitorInSecondary =
1572 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001573
1574 // Test inject a key down.
1575 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1576 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1577 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001578 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001579 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001580 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001581}
1582
Jackal Guof9696682018-10-05 12:23:23 +08001583class InputFilterTest : public InputDispatcherTest {
1584protected:
1585 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1586
1587 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1588 NotifyMotionArgs motionArgs;
1589
1590 motionArgs = generateMotionArgs(
1591 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1592 mDispatcher->notifyMotion(&motionArgs);
1593 motionArgs = generateMotionArgs(
1594 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1595 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001596 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001597 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001598 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001599 } else {
1600 mFakePolicy->assertFilterInputEventWasNotCalled();
1601 }
1602 }
1603
1604 void testNotifyKey(bool expectToBeFiltered) {
1605 NotifyKeyArgs keyArgs;
1606
1607 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1608 mDispatcher->notifyKey(&keyArgs);
1609 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1610 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001611 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001612
1613 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001614 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001615 } else {
1616 mFakePolicy->assertFilterInputEventWasNotCalled();
1617 }
1618 }
1619};
1620
1621// Test InputFilter for MotionEvent
1622TEST_F(InputFilterTest, MotionEvent_InputFilter) {
1623 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
1624 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1625 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1626
1627 // Enable InputFilter
1628 mDispatcher->setInputFilterEnabled(true);
1629 // Test touch on both primary and second display, and check if both events are filtered.
1630 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
1631 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
1632
1633 // Disable InputFilter
1634 mDispatcher->setInputFilterEnabled(false);
1635 // Test touch on both primary and second display, and check if both events aren't filtered.
1636 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1637 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1638}
1639
1640// Test InputFilter for KeyEvent
1641TEST_F(InputFilterTest, KeyEvent_InputFilter) {
1642 // Since the InputFilter is disabled by default, check if key event aren't filtered.
1643 testNotifyKey(/*expectToBeFiltered*/ false);
1644
1645 // Enable InputFilter
1646 mDispatcher->setInputFilterEnabled(true);
1647 // Send a key event, and check if it is filtered.
1648 testNotifyKey(/*expectToBeFiltered*/ true);
1649
1650 // Disable InputFilter
1651 mDispatcher->setInputFilterEnabled(false);
1652 // Send a key event, and check if it isn't filtered.
1653 testNotifyKey(/*expectToBeFiltered*/ false);
1654}
1655
chaviwfd6d3512019-03-25 13:23:49 -07001656class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001657 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07001658 InputDispatcherTest::SetUp();
1659
1660 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1661 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
1662 ADISPLAY_ID_DEFAULT);
1663 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1664 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1665 // window.
1666 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1667
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001668 mFocusedWindow =
1669 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1670 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
1671 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1672 mFocusedWindowTouchPoint = 60;
chaviwfd6d3512019-03-25 13:23:49 -07001673
1674 // Set focused application.
1675 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001676 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07001677
1678 // Expect one focus window exist in display.
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001679 mDispatcher->setInputWindows({mUnfocusedWindow, mFocusedWindow}, ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001680 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07001681 }
1682
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001683 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07001684 InputDispatcherTest::TearDown();
1685
1686 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001687 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07001688 }
1689
1690protected:
1691 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001692 sp<FakeWindowHandle> mFocusedWindow;
1693 int32_t mFocusedWindowTouchPoint;
chaviwfd6d3512019-03-25 13:23:49 -07001694};
1695
1696// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1697// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1698// the onPointerDownOutsideFocus callback.
1699TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
1700 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1701 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
1702 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001703
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001704 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07001705 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1706}
1707
1708// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1709// DOWN on the window that doesn't have focus. Ensure no window received the
1710// onPointerDownOutsideFocus callback.
1711TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
1712 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1713 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
1714 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001715
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001716 ASSERT_TRUE(mDispatcher->waitForIdle());
1717 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001718}
1719
1720// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1721// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1722TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1723 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1724 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001725
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001726 ASSERT_TRUE(mDispatcher->waitForIdle());
1727 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001728}
1729
1730// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1731// DOWN on the window that already has focus. Ensure no window received the
1732// onPointerDownOutsideFocus callback.
1733TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1734 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001735 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1736 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1737 mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
chaviwfd6d3512019-03-25 13:23:49 -07001738 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwfd6d3512019-03-25 13:23:49 -07001739
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001740 ASSERT_TRUE(mDispatcher->waitForIdle());
1741 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001742}
1743
chaviwaf87b3e2019-10-01 16:59:28 -07001744// These tests ensures we can send touch events to a single client when there are multiple input
1745// windows that point to the same client token.
1746class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
1747 virtual void SetUp() override {
1748 InputDispatcherTest::SetUp();
1749
1750 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1751 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
1752 ADISPLAY_ID_DEFAULT);
1753 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
1754 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
1755 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1756 InputWindowInfo::FLAG_SPLIT_TOUCH);
1757 mWindow1->setId(0);
1758 mWindow1->setFrame(Rect(0, 0, 100, 100));
1759
1760 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
1761 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
1762 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1763 InputWindowInfo::FLAG_SPLIT_TOUCH);
1764 mWindow2->setId(1);
1765 mWindow2->setFrame(Rect(100, 100, 200, 200));
1766
1767 mDispatcher->setInputWindows({mWindow1, mWindow2}, ADISPLAY_ID_DEFAULT);
1768 }
1769
1770protected:
1771 sp<FakeWindowHandle> mWindow1;
1772 sp<FakeWindowHandle> mWindow2;
1773
1774 // Helper function to convert the point from screen coordinates into the window's space
1775 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
1776 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
1777 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
1778 return {x, y};
1779 }
1780
1781 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
1782 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001783 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07001784 InputEvent* event = window->consume();
1785
1786 ASSERT_NE(nullptr, event) << name.c_str()
1787 << ": consumer should have returned non-NULL event.";
1788
1789 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
1790 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
1791 << " event, got " << inputEventTypeToString(event->getType()) << " event";
1792
1793 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
1794 EXPECT_EQ(expectedAction, motionEvent.getAction());
1795
1796 for (size_t i = 0; i < points.size(); i++) {
1797 float expectedX = points[i].x;
1798 float expectedY = points[i].y;
1799
1800 EXPECT_EQ(expectedX, motionEvent.getX(i))
1801 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
1802 << ", got " << motionEvent.getX(i);
1803 EXPECT_EQ(expectedY, motionEvent.getY(i))
1804 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
1805 << ", got " << motionEvent.getY(i);
1806 }
1807 }
1808};
1809
1810TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
1811 // Touch Window 1
1812 PointF touchedPoint = {10, 10};
1813 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
1814
1815 NotifyMotionArgs motionArgs =
1816 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1817 ADISPLAY_ID_DEFAULT, {touchedPoint});
1818 mDispatcher->notifyMotion(&motionArgs);
1819 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1820
1821 // Release touch on Window 1
1822 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1823 ADISPLAY_ID_DEFAULT, {touchedPoint});
1824 mDispatcher->notifyMotion(&motionArgs);
1825 // consume the UP event
1826 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
1827
1828 // Touch Window 2
1829 touchedPoint = {150, 150};
1830 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
1831
1832 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1833 ADISPLAY_ID_DEFAULT, {touchedPoint});
1834 mDispatcher->notifyMotion(&motionArgs);
1835
1836 // Consuming from window1 since it's the window that has the InputReceiver
1837 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1838}
1839
1840TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
1841 mWindow2->setWindowScale(0.5f, 0.5f);
1842
1843 // Touch Window 1
1844 PointF touchedPoint = {10, 10};
1845 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
1846
1847 NotifyMotionArgs motionArgs =
1848 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1849 ADISPLAY_ID_DEFAULT, {touchedPoint});
1850 mDispatcher->notifyMotion(&motionArgs);
1851 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1852
1853 // Release touch on Window 1
1854 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1855 ADISPLAY_ID_DEFAULT, {touchedPoint});
1856 mDispatcher->notifyMotion(&motionArgs);
1857 // consume the UP event
1858 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
1859
1860 // Touch Window 2
1861 touchedPoint = {150, 150};
1862 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
1863
1864 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1865 ADISPLAY_ID_DEFAULT, {touchedPoint});
1866 mDispatcher->notifyMotion(&motionArgs);
1867
1868 // Consuming from window1 since it's the window that has the InputReceiver
1869 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
1870}
1871
Chavi Weingarten65f98b82020-01-16 18:56:50 +00001872TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
1873 mWindow2->setWindowScale(0.5f, 0.5f);
1874
1875 // Touch Window 1
1876 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1877 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1878
1879 NotifyMotionArgs motionArgs =
1880 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1881 ADISPLAY_ID_DEFAULT, touchedPoints);
1882 mDispatcher->notifyMotion(&motionArgs);
1883 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1884
1885 // Touch Window 2
1886 int32_t actionPointerDown =
1887 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1888 touchedPoints.emplace_back(PointF{150, 150});
1889 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1890
1891 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1892 ADISPLAY_ID_DEFAULT, touchedPoints);
1893 mDispatcher->notifyMotion(&motionArgs);
1894
1895 // Consuming from window1 since it's the window that has the InputReceiver
1896 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1897}
1898
1899TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
1900 mWindow2->setWindowScale(0.5f, 0.5f);
1901
1902 // Touch Window 1
1903 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1904 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1905
1906 NotifyMotionArgs motionArgs =
1907 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1908 ADISPLAY_ID_DEFAULT, touchedPoints);
1909 mDispatcher->notifyMotion(&motionArgs);
1910 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1911
1912 // Touch Window 2
1913 int32_t actionPointerDown =
1914 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1915 touchedPoints.emplace_back(PointF{150, 150});
1916 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1917
1918 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1919 ADISPLAY_ID_DEFAULT, touchedPoints);
1920 mDispatcher->notifyMotion(&motionArgs);
1921
1922 // Consuming from window1 since it's the window that has the InputReceiver
1923 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1924
1925 // Move both windows
1926 touchedPoints = {{20, 20}, {175, 175}};
1927 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
1928 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
1929
1930 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1931 ADISPLAY_ID_DEFAULT, touchedPoints);
1932 mDispatcher->notifyMotion(&motionArgs);
1933
1934 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
1935}
1936
1937TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
1938 mWindow1->setWindowScale(0.5f, 0.5f);
1939
1940 // Touch Window 1
1941 std::vector<PointF> touchedPoints = {PointF{10, 10}};
1942 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
1943
1944 NotifyMotionArgs motionArgs =
1945 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1946 ADISPLAY_ID_DEFAULT, touchedPoints);
1947 mDispatcher->notifyMotion(&motionArgs);
1948 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
1949
1950 // Touch Window 2
1951 int32_t actionPointerDown =
1952 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1953 touchedPoints.emplace_back(PointF{150, 150});
1954 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
1955
1956 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
1957 ADISPLAY_ID_DEFAULT, touchedPoints);
1958 mDispatcher->notifyMotion(&motionArgs);
1959
1960 // Consuming from window1 since it's the window that has the InputReceiver
1961 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
1962
1963 // Move both windows
1964 touchedPoints = {{20, 20}, {175, 175}};
1965 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
1966 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
1967
1968 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1969 ADISPLAY_ID_DEFAULT, touchedPoints);
1970 mDispatcher->notifyMotion(&motionArgs);
1971
1972 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
1973}
1974
Garfield Tane84e6f92019-08-29 17:28:41 -07001975} // namespace android::inputdispatcher