blob: e94737ff96a9bee809c57ad708345611e2766012 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tan1c7bc862020-01-28 13:24:04 -080019#include <android-base/stringprintf.h>
Robert Carr803535b2018-08-02 16:38:15 -070020#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080021#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070022
Michael Wrightd02c5b62014-02-10 15:10:22 -080023#include <gtest/gtest.h>
24#include <linux/input.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080025#include <cinttypes>
26#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080027#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028
Garfield Tan1c7bc862020-01-28 13:24:04 -080029using android::base::StringPrintf;
30
Garfield Tane84e6f92019-08-29 17:28:41 -070031namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080032
33// An arbitrary time value.
34static const nsecs_t ARBITRARY_TIME = 1234;
35
36// An arbitrary device id.
37static const int32_t DEVICE_ID = 1;
38
Jeff Brownf086ddb2014-02-11 14:28:48 -080039// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080040static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080041
Michael Wrightd02c5b62014-02-10 15:10:22 -080042// An arbitrary injector pid / uid pair that has permission to inject events.
43static const int32_t INJECTOR_PID = 999;
44static const int32_t INJECTOR_UID = 1001;
45
chaviwd1c23182019-12-20 18:44:56 -080046struct PointF {
47 float x;
48 float y;
49};
Michael Wrightd02c5b62014-02-10 15:10:22 -080050
Gang Wang342c9272020-01-13 13:15:04 -050051/**
52 * Return a DOWN key event with KEYCODE_A.
53 */
54static KeyEvent getTestKeyEvent() {
55 KeyEvent event;
56
Garfield Tanfbe732e2020-01-24 11:26:14 -080057 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
58 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
59 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050060 return event;
61}
62
Michael Wrightd02c5b62014-02-10 15:10:22 -080063// --- FakeInputDispatcherPolicy ---
64
65class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
66 InputDispatcherConfiguration mConfig;
67
68protected:
69 virtual ~FakeInputDispatcherPolicy() {
70 }
71
72public:
73 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080074 }
75
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080076 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080077 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
78 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080079 }
80
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080081 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080082 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
83 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080084 }
85
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080086 void assertFilterInputEventWasNotCalled() { ASSERT_EQ(nullptr, mFilteredEvent); }
Michael Wrightd02c5b62014-02-10 15:10:22 -080087
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080088 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
89 ASSERT_TRUE(mConfigurationChangedTime)
90 << "Timed out waiting for configuration changed call";
91 ASSERT_EQ(*mConfigurationChangedTime, when);
92 mConfigurationChangedTime = std::nullopt;
93 }
94
95 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
96 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -080097 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080098 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
99 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
100 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
101 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
102 mLastNotifySwitch = std::nullopt;
103 }
104
chaviwfd6d3512019-03-25 13:23:49 -0700105 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800106 ASSERT_EQ(touchedToken, mOnPointerDownToken);
107 mOnPointerDownToken.clear();
108 }
109
110 void assertOnPointerDownWasNotCalled() {
111 ASSERT_TRUE(mOnPointerDownToken == nullptr)
112 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700113 }
114
Garfield Tan1c7bc862020-01-28 13:24:04 -0800115 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
116 mConfig.keyRepeatTimeout = timeout;
117 mConfig.keyRepeatDelay = delay;
118 }
119
Michael Wrightd02c5b62014-02-10 15:10:22 -0800120private:
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800121 std::unique_ptr<InputEvent> mFilteredEvent;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800122 std::optional<nsecs_t> mConfigurationChangedTime;
chaviwfd6d3512019-03-25 13:23:49 -0700123 sp<IBinder> mOnPointerDownToken;
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800124 std::optional<NotifySwitchArgs> mLastNotifySwitch;
Jackal Guof9696682018-10-05 12:23:23 +0800125
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800126 virtual void notifyConfigurationChanged(nsecs_t when) override {
127 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800128 }
129
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100130 virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
Robert Carr803535b2018-08-02 16:38:15 -0700131 const sp<IBinder>&,
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800132 const std::string&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800133 return 0;
134 }
135
Robert Carr803535b2018-08-02 16:38:15 -0700136 virtual void notifyInputChannelBroken(const sp<IBinder>&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800137 }
138
chaviw0c06c6e2019-01-09 13:27:07 -0800139 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
Robert Carr740167f2018-10-11 19:03:41 -0700140 }
141
Michael Wrightd02c5b62014-02-10 15:10:22 -0800142 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
143 *outConfig = mConfig;
144 }
145
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800146 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Jackal Guof9696682018-10-05 12:23:23 +0800147 switch (inputEvent->getType()) {
148 case AINPUT_EVENT_TYPE_KEY: {
149 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800150 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800151 break;
152 }
153
154 case AINPUT_EVENT_TYPE_MOTION: {
155 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800156 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800157 break;
158 }
159 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800160 return true;
161 }
162
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100163 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800164 }
165
Charles Chen3611f1f2019-01-29 17:26:18 +0800166 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800167 }
168
Robert Carr803535b2018-08-02 16:38:15 -0700169 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100170 const KeyEvent*, uint32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800171 return 0;
172 }
173
Robert Carr803535b2018-08-02 16:38:15 -0700174 virtual bool dispatchUnhandledKey(const sp<IBinder>&,
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100175 const KeyEvent*, uint32_t, KeyEvent*) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176 return false;
177 }
178
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800179 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
180 uint32_t policyFlags) override {
181 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
182 * essentially a passthrough for notifySwitch.
183 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800184 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800185 }
186
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100187 virtual void pokeUserActivity(nsecs_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800188 }
189
Narayan Kamath39efe3e2014-10-17 10:37:08 +0100190 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800191 return false;
192 }
Jackal Guof9696682018-10-05 12:23:23 +0800193
chaviwfd6d3512019-03-25 13:23:49 -0700194 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) {
195 mOnPointerDownToken = newToken;
196 }
197
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800198 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
199 int32_t displayId) {
200 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
201 ASSERT_EQ(mFilteredEvent->getType(), type);
202
203 if (type == AINPUT_EVENT_TYPE_KEY) {
204 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
205 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
206 EXPECT_EQ(keyEvent.getAction(), action);
207 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
208 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
209 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
210 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
211 EXPECT_EQ(motionEvent.getAction(), action);
212 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
213 } else {
214 FAIL() << "Unknown type: " << type;
215 }
216
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800217 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800218 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800219};
220
Gang Wang342c9272020-01-13 13:15:04 -0500221// --- HmacKeyManagerTest ---
222
223class HmacKeyManagerTest : public testing::Test {
224protected:
225 HmacKeyManager mHmacKeyManager;
226};
227
228/**
229 * Ensure that separate calls to sign the same data are generating the same key.
230 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
231 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
232 * tests.
233 */
234TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
235 KeyEvent event = getTestKeyEvent();
236 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
237
238 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
239 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
240 ASSERT_EQ(hmac1, hmac2);
241}
242
243/**
244 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
245 */
246TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
247 KeyEvent event = getTestKeyEvent();
248 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
249 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
250
251 verifiedEvent.deviceId += 1;
252 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
253
254 verifiedEvent.source += 1;
255 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
256
257 verifiedEvent.eventTimeNanos += 1;
258 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
259
260 verifiedEvent.displayId += 1;
261 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
262
263 verifiedEvent.action += 1;
264 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
265
266 verifiedEvent.downTimeNanos += 1;
267 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
268
269 verifiedEvent.flags += 1;
270 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
271
272 verifiedEvent.keyCode += 1;
273 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
274
275 verifiedEvent.scanCode += 1;
276 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
277
278 verifiedEvent.metaState += 1;
279 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
280
281 verifiedEvent.repeatCount += 1;
282 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
283}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800284
285// --- InputDispatcherTest ---
286
287class InputDispatcherTest : public testing::Test {
288protected:
289 sp<FakeInputDispatcherPolicy> mFakePolicy;
290 sp<InputDispatcher> mDispatcher;
291
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700292 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800293 mFakePolicy = new FakeInputDispatcherPolicy();
294 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800295 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
296 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700297 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800298 }
299
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700300 virtual void TearDown() override {
301 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800302 mFakePolicy.clear();
303 mDispatcher.clear();
304 }
305};
306
307
308TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
309 KeyEvent event;
310
311 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800312 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
313 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600314 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
315 ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800316 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800317 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800318 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
319 << "Should reject key events with undefined action.";
320
321 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800322 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
323 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600324 ARBITRARY_TIME, ARBITRARY_TIME);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800325 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800326 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800327 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
328 << "Should reject key events with ACTION_MULTIPLE.";
329}
330
331TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
332 MotionEvent event;
333 PointerProperties pointerProperties[MAX_POINTERS + 1];
334 PointerCoords pointerCoords[MAX_POINTERS + 1];
335 for (int i = 0; i <= MAX_POINTERS; i++) {
336 pointerProperties[i].clear();
337 pointerProperties[i].id = i;
338 pointerCoords[i].clear();
339 }
340
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800341 // Some constants commonly used below
342 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
343 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
344 constexpr int32_t metaState = AMETA_NONE;
345 constexpr MotionClassification classification = MotionClassification::NONE;
346
Michael Wrightd02c5b62014-02-10 15:10:22 -0800347 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800348 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600349 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
350 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
351 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700352 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800353 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800354 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800355 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
356 << "Should reject motion events with undefined action.";
357
358 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800359 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700360 AMOTION_EVENT_ACTION_POINTER_DOWN |
361 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600362 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
363 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
364 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700365 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800366 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800367 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800368 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
369 << "Should reject motion events with pointer down index too large.";
370
Garfield Tanfbe732e2020-01-24 11:26:14 -0800371 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700372 AMOTION_EVENT_ACTION_POINTER_DOWN |
373 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600374 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
375 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
376 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700377 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800378 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800379 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800380 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
381 << "Should reject motion events with pointer down index too small.";
382
383 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800384 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700385 AMOTION_EVENT_ACTION_POINTER_UP |
386 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600387 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
388 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
389 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700390 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800391 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800392 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800393 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
394 << "Should reject motion events with pointer up index too large.";
395
Garfield Tanfbe732e2020-01-24 11:26:14 -0800396 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700397 AMOTION_EVENT_ACTION_POINTER_UP |
398 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600399 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
400 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
401 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700402 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800403 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800404 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800405 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
406 << "Should reject motion events with pointer up index too small.";
407
408 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800409 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
410 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
411 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
412 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
413 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700414 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800415 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800416 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800417 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
418 << "Should reject motion events with 0 pointers.";
419
Garfield Tanfbe732e2020-01-24 11:26:14 -0800420 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
421 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
422 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
423 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
424 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700425 /*pointerCount*/ MAX_POINTERS + 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 more than MAX_POINTERS pointers.";
430
431 // Rejects motion events with invalid pointer ids.
432 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800433 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
434 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
435 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
436 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
437 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700438 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800439 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800440 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800441 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
442 << "Should reject motion events with pointer ids less than 0.";
443
444 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800445 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
446 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
447 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
448 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
449 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700450 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800451 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800452 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800453 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
454 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
455
456 // Rejects motion events with duplicate pointer ids.
457 pointerProperties[0].id = 1;
458 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800459 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
460 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
461 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
462 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
463 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700464 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Jeff Brownf086ddb2014-02-11 14:28:48 -0800465 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -0800466 &event,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800467 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
468 << "Should reject motion events with duplicate pointer ids.";
469}
470
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800471/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
472
473TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
474 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800475 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800476 mDispatcher->notifyConfigurationChanged(&args);
477 ASSERT_TRUE(mDispatcher->waitForIdle());
478
479 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
480}
481
482TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800483 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
484 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800485 mDispatcher->notifySwitch(&args);
486
487 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
488 args.policyFlags |= POLICY_FLAG_TRUSTED;
489 mFakePolicy->assertNotifySwitchWasCalled(args);
490}
491
Arthur Hungb92218b2018-08-14 12:00:21 +0800492// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800493static constexpr int32_t INJECT_EVENT_TIMEOUT = 500;
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -0700494static constexpr nsecs_t DISPATCHING_TIMEOUT = seconds_to_nanoseconds(5);
Arthur Hungb92218b2018-08-14 12:00:21 +0800495
496class FakeApplicationHandle : public InputApplicationHandle {
497public:
498 FakeApplicationHandle() {}
499 virtual ~FakeApplicationHandle() {}
500
501 virtual bool updateInfo() {
Arthur Hung7a0c39a2019-03-20 16:52:24 +0800502 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Arthur Hungb92218b2018-08-14 12:00:21 +0800503 return true;
504 }
505};
506
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800507class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800508public:
chaviwd1c23182019-12-20 18:44:56 -0800509 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
510 : mName(name) {
511 mConsumer = std::make_unique<InputConsumer>(clientChannel);
512 }
513
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800514 InputEvent* consume() {
Arthur Hungb92218b2018-08-14 12:00:21 +0800515 uint32_t consumeSeq;
516 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800517
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800518 std::chrono::time_point start = std::chrono::steady_clock::now();
519 status_t status = WOULD_BLOCK;
520 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800521 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800522 &event);
523 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
524 if (elapsed > 100ms) {
525 break;
526 }
527 }
528
529 if (status == WOULD_BLOCK) {
530 // Just means there's no event available.
531 return nullptr;
532 }
533
534 if (status != OK) {
535 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
536 return nullptr;
537 }
538 if (event == nullptr) {
539 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
540 return nullptr;
541 }
542
chaviwd1c23182019-12-20 18:44:56 -0800543 status = mConsumer->sendFinishedSignal(consumeSeq, true);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800544 if (status != OK) {
545 ADD_FAILURE() << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
546 }
547 return event;
548 }
549
550 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
551 int32_t expectedFlags) {
552 InputEvent* event = consume();
553
554 ASSERT_NE(nullptr, event) << mName.c_str()
555 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800556 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800557 << mName.c_str() << "expected " << inputEventTypeToString(expectedEventType)
558 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800559
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800560 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800561
Tiger Huang8664f8c2018-10-11 19:14:35 +0800562 switch (expectedEventType) {
563 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800564 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
565 EXPECT_EQ(expectedAction, keyEvent.getAction());
566 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800567 break;
568 }
569 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800570 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
571 EXPECT_EQ(expectedAction, motionEvent.getAction());
572 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800573 break;
574 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100575 case AINPUT_EVENT_TYPE_FOCUS: {
576 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
577 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800578 default: {
579 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
580 }
581 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800582 }
583
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100584 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
585 InputEvent* event = consume();
586 ASSERT_NE(nullptr, event) << mName.c_str()
587 << ": consumer should have returned non-NULL event.";
588 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
589 << "Got " << inputEventTypeToString(event->getType())
590 << " event instead of FOCUS event";
591
592 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
593 << mName.c_str() << ": event displayId should always be NONE.";
594
595 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
596 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
597 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
598 }
599
chaviwd1c23182019-12-20 18:44:56 -0800600 void assertNoEvents() {
601 InputEvent* event = consume();
602 ASSERT_EQ(nullptr, event)
603 << mName.c_str()
604 << ": should not have received any events, so consume() should return NULL";
605 }
606
607 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
608
609protected:
610 std::unique_ptr<InputConsumer> mConsumer;
611 PreallocatedInputEventFactory mEventFactory;
612
613 std::string mName;
614};
615
616class FakeWindowHandle : public InputWindowHandle {
617public:
618 static const int32_t WIDTH = 600;
619 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800620
621 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
622 const sp<InputDispatcher>& dispatcher, const std::string name,
623 int32_t displayId, sp<IBinder> token = nullptr)
624 : mName(name) {
625 if (token == nullptr) {
626 sp<InputChannel> serverChannel, clientChannel;
627 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
628 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
629 dispatcher->registerInputChannel(serverChannel);
630 token = serverChannel->getConnectionToken();
631 }
632
633 inputApplicationHandle->updateInfo();
634 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
635
636 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700637 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800638 mInfo.name = name;
639 mInfo.layoutParamsFlags = 0;
640 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
641 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
642 mInfo.frameLeft = 0;
643 mInfo.frameTop = 0;
644 mInfo.frameRight = WIDTH;
645 mInfo.frameBottom = HEIGHT;
646 mInfo.globalScaleFactor = 1.0;
647 mInfo.touchableRegion.clear();
648 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
649 mInfo.visible = true;
650 mInfo.canReceiveKeys = true;
651 mInfo.hasFocus = false;
652 mInfo.hasWallpaper = false;
653 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800654 mInfo.ownerPid = INJECTOR_PID;
655 mInfo.ownerUid = INJECTOR_UID;
656 mInfo.inputFeatures = 0;
657 mInfo.displayId = displayId;
658 }
659
660 virtual bool updateInfo() { return true; }
661
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100662 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800663
664 void setFrame(const Rect& frame) {
665 mInfo.frameLeft = frame.left;
666 mInfo.frameTop = frame.top;
667 mInfo.frameRight = frame.right;
668 mInfo.frameBottom = frame.bottom;
669 mInfo.touchableRegion.clear();
670 mInfo.addTouchableRegion(frame);
671 }
672
673 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
674
chaviwaf87b3e2019-10-01 16:59:28 -0700675 void setWindowScale(float xScale, float yScale) {
676 mInfo.windowXScale = xScale;
677 mInfo.windowYScale = yScale;
678 }
679
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800680 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
681 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
682 expectedFlags);
683 }
684
Svet Ganov5d3bc372020-01-26 23:11:07 -0800685 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
686 int32_t expectedFlags = 0) {
687 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
688 expectedFlags);
689 }
690
691 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
692 int32_t expectedFlags = 0) {
693 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
694 expectedFlags);
695 }
696
697 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
698 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800699 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
700 expectedFlags);
701 }
702
Svet Ganov5d3bc372020-01-26 23:11:07 -0800703 void consumeMotionPointerDown(int32_t pointerIdx,
704 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
705 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
706 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
707 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
708 }
709
710 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
711 int32_t expectedFlags = 0) {
712 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
713 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
714 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
715 }
716
717 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
718 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000719 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
720 expectedFlags);
721 }
722
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100723 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
724 ASSERT_NE(mInputReceiver, nullptr)
725 << "Cannot consume events from a window with no receiver";
726 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
727 }
728
chaviwd1c23182019-12-20 18:44:56 -0800729 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
730 int32_t expectedFlags) {
731 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
732 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
733 expectedFlags);
734 }
735
chaviwaf87b3e2019-10-01 16:59:28 -0700736 InputEvent* consume() {
737 if (mInputReceiver == nullptr) {
738 return nullptr;
739 }
740 return mInputReceiver->consume();
741 }
742
Arthur Hungb92218b2018-08-14 12:00:21 +0800743 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800744 ASSERT_NE(mInputReceiver, nullptr)
745 << "Call 'assertNoEvents' on a window with an InputReceiver";
746 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800747 }
748
chaviwaf87b3e2019-10-01 16:59:28 -0700749 sp<IBinder> getToken() { return mInfo.token; }
750
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100751 const std::string& getName() { return mName; }
752
chaviwd1c23182019-12-20 18:44:56 -0800753private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100754 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800755 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700756 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800757};
758
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700759std::atomic<int32_t> FakeWindowHandle::sId{1};
760
Tiger Huang721e26f2018-07-24 22:26:19 +0800761static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
762 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800763 KeyEvent event;
764 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
765
766 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
768 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
769 AMETA_NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600770 /* repeatCount */ 0, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800771
772 // Inject event until dispatch out.
773 return dispatcher->injectInputEvent(
774 &event,
775 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
776 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
777}
778
Garfield Tan00f511d2019-06-12 16:55:40 -0700779static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t action,
780 int32_t source, int32_t displayId, int32_t x, int32_t y,
781 int32_t xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION,
782 int32_t yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800783 MotionEvent event;
784 PointerProperties pointerProperties[1];
785 PointerCoords pointerCoords[1];
786
787 pointerProperties[0].clear();
788 pointerProperties[0].id = 0;
789 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
790
791 pointerCoords[0].clear();
chaviwfd6d3512019-03-25 13:23:49 -0700792 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
793 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800794
795 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
796 // Define a valid motion down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800797 event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
798 /* actionButton */ 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600799 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700800 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600801 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
802 /* xPrecision */ 0, /* yPrecision */ 0, xCursorPosition, yCursorPosition,
803 currentTime, currentTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700804 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800805
806 // Inject event until dispatch out.
807 return dispatcher->injectInputEvent(
808 &event,
809 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
810 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
811}
812
Garfield Tan00f511d2019-06-12 16:55:40 -0700813static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700814 int32_t displayId, const PointF& location = {100, 200}) {
815 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location.x,
816 location.y);
Garfield Tan00f511d2019-06-12 16:55:40 -0700817}
818
Michael Wright3a240c42019-12-10 20:53:41 +0000819static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700820 int32_t displayId, const PointF& location = {100, 200}) {
821 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location.x,
822 location.y);
Michael Wright3a240c42019-12-10 20:53:41 +0000823}
824
Jackal Guof9696682018-10-05 12:23:23 +0800825static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
826 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
827 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800828 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
829 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
830 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800831
832 return args;
833}
834
chaviwd1c23182019-12-20 18:44:56 -0800835static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
836 const std::vector<PointF>& points) {
837 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700838 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
839 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
840 }
841
chaviwd1c23182019-12-20 18:44:56 -0800842 PointerProperties pointerProperties[pointerCount];
843 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800844
chaviwd1c23182019-12-20 18:44:56 -0800845 for (size_t i = 0; i < pointerCount; i++) {
846 pointerProperties[i].clear();
847 pointerProperties[i].id = i;
848 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800849
chaviwd1c23182019-12-20 18:44:56 -0800850 pointerCoords[i].clear();
851 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
852 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
853 }
Jackal Guof9696682018-10-05 12:23:23 +0800854
855 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
856 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800857 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700858 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
859 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800860 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
861 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700862 AMOTION_EVENT_INVALID_CURSOR_POSITION,
863 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800864
865 return args;
866}
867
chaviwd1c23182019-12-20 18:44:56 -0800868static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
869 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
870}
871
Arthur Hungb92218b2018-08-14 12:00:21 +0800872TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
873 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800874 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
875 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800876
Arthur Hung72d8dc32020-03-28 00:48:39 +0000877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800878 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
879 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800880 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
881
882 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800883 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800884}
885
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700886/**
887 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
888 * To ensure that window receives only events that were directly inside of it, add
889 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
890 * when finding touched windows.
891 * This test serves as a sanity check for the next test, where setInputWindows is
892 * called twice.
893 */
894TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
895 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
896 sp<FakeWindowHandle> window =
897 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
898 window->setFrame(Rect(0, 0, 100, 100));
899 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
900
901 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
902 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
903 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
904 {50, 50}))
905 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
906
907 // Window should receive motion event.
908 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
909}
910
911/**
912 * Calling setInputWindows twice, with the same info, should not cause any issues.
913 * To ensure that window receives only events that were directly inside of it, add
914 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
915 * when finding touched windows.
916 */
917TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
918 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
919 sp<FakeWindowHandle> window =
920 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
921 window->setFrame(Rect(0, 0, 100, 100));
922 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
923
924 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
925 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
926 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
927 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
928 {50, 50}))
929 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
930
931 // Window should receive motion event.
932 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
933}
934
Arthur Hungb92218b2018-08-14 12:00:21 +0800935// The foreground window should receive the first touch down event.
936TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
937 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800938 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
939 ADISPLAY_ID_DEFAULT);
940 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
941 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800942
Arthur Hung72d8dc32020-03-28 00:48:39 +0000943 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800944 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
945 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800946 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
947
948 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800949 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800950 windowSecond->assertNoEvents();
951}
952
953TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
954 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800955 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
956 ADISPLAY_ID_DEFAULT);
957 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
958 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800959
Arthur Hung7ab76b12019-01-09 19:17:20 +0800960 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +0800961 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +0800962
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100963 // Display should have only one focused window
964 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +0000965 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100966
967 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +0800968 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
969 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
970
971 // Focused window should receive event.
972 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800973 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +0800974}
975
Arthur Hung7ab76b12019-01-09 19:17:20 +0800976TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
977 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
978 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
979 ADISPLAY_ID_DEFAULT);
980 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
981 ADISPLAY_ID_DEFAULT);
982
983 // Set focused application.
984 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
985
986 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100987 windowTop->setFocus(true);
988 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800989
Arthur Hung72d8dc32020-03-28 00:48:39 +0000990 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100991 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800992 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
993 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
994
995 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800996 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +0800997 windowSecond->assertNoEvents();
998}
999
Arthur Hung3b413f22018-10-26 18:05:34 +08001000TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
1001 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1002
1003 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1004 ADISPLAY_ID_DEFAULT);
1005 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1006 ADISPLAY_ID_DEFAULT);
1007
Arthur Hung832bc4a2019-01-28 11:43:17 +08001008 // Set focused application.
1009 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001010
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001011 windowTop->setFocus(true);
1012 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001013 // Release channel for window is no longer valid.
1014 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001015 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001016 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001017
Arthur Hung832bc4a2019-01-28 11:43:17 +08001018 // Test inject a key down, should dispatch to a valid window.
1019 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1020 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001021
1022 // Top window is invalid, so it should not receive any input event.
1023 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001024 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001025}
1026
Garfield Tan00f511d2019-06-12 16:55:40 -07001027TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
1028 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1029
1030 sp<FakeWindowHandle> windowLeft =
1031 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1032 windowLeft->setFrame(Rect(0, 0, 600, 800));
1033 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1034 sp<FakeWindowHandle> windowRight =
1035 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1036 windowRight->setFrame(Rect(600, 0, 1200, 800));
1037 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1038
1039 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1040
Arthur Hung72d8dc32020-03-28 00:48:39 +00001041 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001042
1043 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1044 // left window. This event should be dispatched to the left window.
1045 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1046 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
1047 ADISPLAY_ID_DEFAULT, 610, 400, 599, 400));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001048 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001049 windowRight->assertNoEvents();
1050}
1051
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001052TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
1053 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1054 sp<FakeWindowHandle> window =
1055 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001056 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001057
Arthur Hung72d8dc32020-03-28 00:48:39 +00001058 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001059 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001060
1061 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1062 mDispatcher->notifyKey(&keyArgs);
1063
1064 // Window should receive key down event.
1065 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1066
1067 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1068 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001069 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001070 mDispatcher->notifyDeviceReset(&args);
1071 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1072 AKEY_EVENT_FLAG_CANCELED);
1073}
1074
1075TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1076 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1077 sp<FakeWindowHandle> window =
1078 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1079
Arthur Hung72d8dc32020-03-28 00:48:39 +00001080 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001081
1082 NotifyMotionArgs motionArgs =
1083 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1084 ADISPLAY_ID_DEFAULT);
1085 mDispatcher->notifyMotion(&motionArgs);
1086
1087 // Window should receive motion down event.
1088 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1089
1090 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1091 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001092 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001093 mDispatcher->notifyDeviceReset(&args);
1094 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1095 0 /*expectedFlags*/);
1096}
1097
Svet Ganov5d3bc372020-01-26 23:11:07 -08001098TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1099 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1100
1101 // Create a couple of windows
1102 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1103 "First Window", ADISPLAY_ID_DEFAULT);
1104 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1105 "Second Window", ADISPLAY_ID_DEFAULT);
1106
1107 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001108 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001109
1110 // Send down to the first window
1111 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1112 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1113 mDispatcher->notifyMotion(&downMotionArgs);
1114 // Only the first window should get the down event
1115 firstWindow->consumeMotionDown();
1116 secondWindow->assertNoEvents();
1117
1118 // Transfer touch focus to the second window
1119 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1120 // The first window gets cancel and the second gets down
1121 firstWindow->consumeMotionCancel();
1122 secondWindow->consumeMotionDown();
1123
1124 // Send up event to the second window
1125 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1126 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1127 mDispatcher->notifyMotion(&upMotionArgs);
1128 // The first window gets no events and the second gets up
1129 firstWindow->assertNoEvents();
1130 secondWindow->consumeMotionUp();
1131}
1132
1133TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1134 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1135
1136 PointF touchPoint = {10, 10};
1137
1138 // Create a couple of windows
1139 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1140 "First Window", ADISPLAY_ID_DEFAULT);
1141 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1142 "Second Window", ADISPLAY_ID_DEFAULT);
1143
1144 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001145 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001146
1147 // Send down to the first window
1148 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1149 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1150 mDispatcher->notifyMotion(&downMotionArgs);
1151 // Only the first window should get the down event
1152 firstWindow->consumeMotionDown();
1153 secondWindow->assertNoEvents();
1154
1155 // Send pointer down to the first window
1156 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1157 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1158 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1159 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1160 // Only the first window should get the pointer down event
1161 firstWindow->consumeMotionPointerDown(1);
1162 secondWindow->assertNoEvents();
1163
1164 // Transfer touch focus to the second window
1165 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1166 // The first window gets cancel and the second gets down and pointer down
1167 firstWindow->consumeMotionCancel();
1168 secondWindow->consumeMotionDown();
1169 secondWindow->consumeMotionPointerDown(1);
1170
1171 // Send pointer up to the second window
1172 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1173 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1174 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1175 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1176 // The first window gets nothing and the second gets pointer up
1177 firstWindow->assertNoEvents();
1178 secondWindow->consumeMotionPointerUp(1);
1179
1180 // Send up event to the second window
1181 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1182 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1183 mDispatcher->notifyMotion(&upMotionArgs);
1184 // The first window gets nothing and the second gets up
1185 firstWindow->assertNoEvents();
1186 secondWindow->consumeMotionUp();
1187}
1188
1189TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1190 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1191
1192 // Create a non touch modal window that supports split touch
1193 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1194 "First Window", ADISPLAY_ID_DEFAULT);
1195 firstWindow->setFrame(Rect(0, 0, 600, 400));
1196 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1197 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1198
1199 // Create a non touch modal window that supports split touch
1200 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1201 "Second Window", ADISPLAY_ID_DEFAULT);
1202 secondWindow->setFrame(Rect(0, 400, 600, 800));
1203 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1204 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1205
1206 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001207 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001208
1209 PointF pointInFirst = {300, 200};
1210 PointF pointInSecond = {300, 600};
1211
1212 // Send down to the first window
1213 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1214 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1215 mDispatcher->notifyMotion(&firstDownMotionArgs);
1216 // Only the first window should get the down event
1217 firstWindow->consumeMotionDown();
1218 secondWindow->assertNoEvents();
1219
1220 // Send down to the second window
1221 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1222 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1223 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1224 mDispatcher->notifyMotion(&secondDownMotionArgs);
1225 // The first window gets a move and the second a down
1226 firstWindow->consumeMotionMove();
1227 secondWindow->consumeMotionDown();
1228
1229 // Transfer touch focus to the second window
1230 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1231 // The first window gets cancel and the new gets pointer down (it already saw down)
1232 firstWindow->consumeMotionCancel();
1233 secondWindow->consumeMotionPointerDown(1);
1234
1235 // Send pointer up to the second window
1236 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1237 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1238 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1239 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1240 // The first window gets nothing and the second gets pointer up
1241 firstWindow->assertNoEvents();
1242 secondWindow->consumeMotionPointerUp(1);
1243
1244 // Send up event to the second window
1245 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1246 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1247 mDispatcher->notifyMotion(&upMotionArgs);
1248 // The first window gets nothing and the second gets up
1249 firstWindow->assertNoEvents();
1250 secondWindow->consumeMotionUp();
1251}
1252
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001253TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1254 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1255 sp<FakeWindowHandle> window =
1256 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1257
1258 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001259 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001260
1261 window->consumeFocusEvent(true);
1262
1263 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1264 mDispatcher->notifyKey(&keyArgs);
1265
1266 // Window should receive key down event.
1267 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1268}
1269
1270TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1271 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1272 sp<FakeWindowHandle> window =
1273 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1274
Arthur Hung72d8dc32020-03-28 00:48:39 +00001275 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001276
1277 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1278 mDispatcher->notifyKey(&keyArgs);
1279 mDispatcher->waitForIdle();
1280
1281 window->assertNoEvents();
1282}
1283
1284// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1285TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1286 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1287 sp<FakeWindowHandle> window =
1288 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1289
Arthur Hung72d8dc32020-03-28 00:48:39 +00001290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001291
1292 // Send key
1293 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1294 mDispatcher->notifyKey(&keyArgs);
1295 // Send motion
1296 NotifyMotionArgs motionArgs =
1297 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1298 ADISPLAY_ID_DEFAULT);
1299 mDispatcher->notifyMotion(&motionArgs);
1300
1301 // Window should receive only the motion event
1302 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1303 window->assertNoEvents(); // Key event or focus event will not be received
1304}
1305
chaviwd1c23182019-12-20 18:44:56 -08001306class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001307public:
1308 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001309 int32_t displayId, bool isGestureMonitor = false) {
1310 sp<InputChannel> serverChannel, clientChannel;
1311 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1312 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1313 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001314 }
1315
chaviwd1c23182019-12-20 18:44:56 -08001316 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1317
1318 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1319 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1320 expectedDisplayId, expectedFlags);
1321 }
1322
1323 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1324 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1325 expectedDisplayId, expectedFlags);
1326 }
1327
1328 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1329 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1330 expectedDisplayId, expectedFlags);
1331 }
1332
1333 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1334
1335private:
1336 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001337};
1338
1339// Tests for gesture monitors
1340TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1341 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1342 sp<FakeWindowHandle> window =
1343 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001344 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001345
chaviwd1c23182019-12-20 18:44:56 -08001346 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1347 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001348
1349 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1350 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1351 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1352 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001353 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001354}
1355
1356TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1357 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1358 sp<FakeWindowHandle> window =
1359 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1360
1361 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001362 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001363
Arthur Hung72d8dc32020-03-28 00:48:39 +00001364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001365 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001366
chaviwd1c23182019-12-20 18:44:56 -08001367 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1368 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001369
1370 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1371 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1372 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001373 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001374}
1375
1376TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1377 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1378 sp<FakeWindowHandle> window =
1379 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001380 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001381
chaviwd1c23182019-12-20 18:44:56 -08001382 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1383 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001384
1385 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1386 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1387 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1388 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001389 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001390
1391 window->releaseChannel();
1392
chaviwd1c23182019-12-20 18:44:56 -08001393 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001394
1395 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1396 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1397 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001398 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001399}
1400
chaviw81e2bb92019-12-18 15:03:51 -08001401TEST_F(InputDispatcherTest, TestMoveEvent) {
1402 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1403 sp<FakeWindowHandle> window =
1404 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1405
Arthur Hung72d8dc32020-03-28 00:48:39 +00001406 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001407
1408 NotifyMotionArgs motionArgs =
1409 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1410 ADISPLAY_ID_DEFAULT);
1411
1412 mDispatcher->notifyMotion(&motionArgs);
1413 // Window should receive motion down event.
1414 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1415
1416 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001417 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001418 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1419 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1420 motionArgs.pointerCoords[0].getX() - 10);
1421
1422 mDispatcher->notifyMotion(&motionArgs);
1423 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1424 0 /*expectedFlags*/);
1425}
1426
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001427/**
1428 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1429 * the device default right away. In the test scenario, we check both the default value,
1430 * and the action of enabling / disabling.
1431 */
1432TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1433 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1434 sp<FakeWindowHandle> window =
1435 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1436
1437 // Set focused application.
1438 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1439 window->setFocus(true);
1440
1441 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001442 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001443 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1444
1445 SCOPED_TRACE("Remove the window to trigger focus loss");
1446 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001448 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1449
1450 SCOPED_TRACE("Disable touch mode");
1451 mDispatcher->setInTouchMode(false);
1452 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001454 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1455
1456 SCOPED_TRACE("Remove the window to trigger focus loss");
1457 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001458 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001459 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1460
1461 SCOPED_TRACE("Enable touch mode again");
1462 mDispatcher->setInTouchMode(true);
1463 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001464 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001465 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1466
1467 window->assertNoEvents();
1468}
1469
Gang Wange9087892020-01-07 12:17:14 -05001470TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1471 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1472 sp<FakeWindowHandle> window =
1473 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1474
1475 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1476 window->setFocus(true);
1477
Arthur Hung72d8dc32020-03-28 00:48:39 +00001478 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001479 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1480
1481 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1482 mDispatcher->notifyKey(&keyArgs);
1483
1484 InputEvent* event = window->consume();
1485 ASSERT_NE(event, nullptr);
1486
1487 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1488 ASSERT_NE(verified, nullptr);
1489 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1490
1491 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1492 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1493 ASSERT_EQ(keyArgs.source, verified->source);
1494 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1495
1496 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1497
1498 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1499 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001500 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1501 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1502 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1503 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1504 ASSERT_EQ(0, verifiedKey.repeatCount);
1505}
1506
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001507TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
1508 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1509 sp<FakeWindowHandle> window =
1510 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1511
1512 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1513
Arthur Hung72d8dc32020-03-28 00:48:39 +00001514 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001515
1516 NotifyMotionArgs motionArgs =
1517 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1518 ADISPLAY_ID_DEFAULT);
1519 mDispatcher->notifyMotion(&motionArgs);
1520
1521 InputEvent* event = window->consume();
1522 ASSERT_NE(event, nullptr);
1523
1524 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1525 ASSERT_NE(verified, nullptr);
1526 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
1527
1528 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
1529 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
1530 EXPECT_EQ(motionArgs.source, verified->source);
1531 EXPECT_EQ(motionArgs.displayId, verified->displayId);
1532
1533 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
1534
1535 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
1536 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
1537 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
1538 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
1539 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
1540 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
1541 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
1542}
1543
Garfield Tan1c7bc862020-01-28 13:24:04 -08001544class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
1545protected:
1546 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
1547 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
1548
1549 sp<FakeApplicationHandle> mApp;
1550 sp<FakeWindowHandle> mWindow;
1551
1552 virtual void SetUp() override {
1553 mFakePolicy = new FakeInputDispatcherPolicy();
1554 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
1555 mDispatcher = new InputDispatcher(mFakePolicy);
1556 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
1557 ASSERT_EQ(OK, mDispatcher->start());
1558
1559 setUpWindow();
1560 }
1561
1562 void setUpWindow() {
1563 mApp = new FakeApplicationHandle();
1564 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1565
1566 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001567 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08001568
1569 mWindow->consumeFocusEvent(true);
1570 }
1571
1572 void sendAndConsumeKeyDown() {
1573 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1574 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
1575 mDispatcher->notifyKey(&keyArgs);
1576
1577 // Window should receive key down event.
1578 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1579 }
1580
1581 void expectKeyRepeatOnce(int32_t repeatCount) {
1582 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
1583 InputEvent* repeatEvent = mWindow->consume();
1584 ASSERT_NE(nullptr, repeatEvent);
1585
1586 uint32_t eventType = repeatEvent->getType();
1587 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
1588
1589 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
1590 uint32_t eventAction = repeatKeyEvent->getAction();
1591 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
1592 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
1593 }
1594
1595 void sendAndConsumeKeyUp() {
1596 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
1597 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
1598 mDispatcher->notifyKey(&keyArgs);
1599
1600 // Window should receive key down event.
1601 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1602 0 /*expectedFlags*/);
1603 }
1604};
1605
1606TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
1607 sendAndConsumeKeyDown();
1608 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1609 expectKeyRepeatOnce(repeatCount);
1610 }
1611}
1612
1613TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
1614 sendAndConsumeKeyDown();
1615 expectKeyRepeatOnce(1 /*repeatCount*/);
1616 sendAndConsumeKeyUp();
1617 mWindow->assertNoEvents();
1618}
1619
1620TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
1621 sendAndConsumeKeyDown();
1622 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1623 InputEvent* repeatEvent = mWindow->consume();
1624 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1625 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
1626 IdGenerator::getSource(repeatEvent->getId()));
1627 }
1628}
1629
1630TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
1631 sendAndConsumeKeyDown();
1632
1633 std::unordered_set<int32_t> idSet;
1634 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1635 InputEvent* repeatEvent = mWindow->consume();
1636 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1637 int32_t id = repeatEvent->getId();
1638 EXPECT_EQ(idSet.end(), idSet.find(id));
1639 idSet.insert(id);
1640 }
1641}
1642
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001643/* Test InputDispatcher for MultiDisplay */
1644class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1645public:
1646 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001647 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001648 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001649
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001650 application1 = new FakeApplicationHandle();
1651 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1652 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001653
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001654 // Set focus window for primary display, but focused display would be second one.
1655 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001656 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001658 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001659
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001660 application2 = new FakeApplicationHandle();
1661 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1662 SECOND_DISPLAY_ID);
1663 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001664 // Set focus display to second one.
1665 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1666 // Set focus window for second display.
1667 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001668 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001669 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001670 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001671 }
1672
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001673 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001674 InputDispatcherTest::TearDown();
1675
1676 application1.clear();
1677 windowInPrimary.clear();
1678 application2.clear();
1679 windowInSecondary.clear();
1680 }
1681
1682protected:
1683 sp<FakeApplicationHandle> application1;
1684 sp<FakeWindowHandle> windowInPrimary;
1685 sp<FakeApplicationHandle> application2;
1686 sp<FakeWindowHandle> windowInSecondary;
1687};
1688
1689TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1690 // Test touch down on primary display.
1691 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1692 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001693 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001694 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001695 windowInSecondary->assertNoEvents();
1696
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001697 // Test touch down on second display.
1698 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1699 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001700 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1701 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001702 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001703}
1704
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001705TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001706 // Test inject a key down with display id specified.
1707 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1708 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001709 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001710 windowInSecondary->assertNoEvents();
1711
1712 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001713 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1714 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1715 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001716 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001717
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001718 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001719 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08001720
1721 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001722 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1723 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001724
1725 // Test inject a key down, should timeout because of no target window.
1726 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1727 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1728 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001729 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001730 windowInSecondary->assertNoEvents();
1731}
1732
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001733// Test per-display input monitors for motion event.
1734TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001735 FakeMonitorReceiver monitorInPrimary =
1736 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1737 FakeMonitorReceiver monitorInSecondary =
1738 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001739
1740 // Test touch down on primary display.
1741 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1742 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1743 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001744 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001745 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001746 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001747 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001748
1749 // Test touch down on second display.
1750 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1751 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1752 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1753 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001754 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001755 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001756 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001757
1758 // Test inject a non-pointer motion event.
1759 // If specific a display, it will dispatch to the focused window of particular display,
1760 // or it will dispatch to the focused window of focused display.
1761 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1762 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1763 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1764 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001765 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001766 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001767 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001768}
1769
1770// Test per-display input monitors for key event.
1771TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1772 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001773 FakeMonitorReceiver monitorInPrimary =
1774 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1775 FakeMonitorReceiver monitorInSecondary =
1776 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001777
1778 // Test inject a key down.
1779 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1780 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1781 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001782 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001783 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001784 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001785}
1786
Jackal Guof9696682018-10-05 12:23:23 +08001787class InputFilterTest : public InputDispatcherTest {
1788protected:
1789 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1790
1791 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1792 NotifyMotionArgs motionArgs;
1793
1794 motionArgs = generateMotionArgs(
1795 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1796 mDispatcher->notifyMotion(&motionArgs);
1797 motionArgs = generateMotionArgs(
1798 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1799 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001800 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001801 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001802 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001803 } else {
1804 mFakePolicy->assertFilterInputEventWasNotCalled();
1805 }
1806 }
1807
1808 void testNotifyKey(bool expectToBeFiltered) {
1809 NotifyKeyArgs keyArgs;
1810
1811 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1812 mDispatcher->notifyKey(&keyArgs);
1813 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1814 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001815 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001816
1817 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001818 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001819 } else {
1820 mFakePolicy->assertFilterInputEventWasNotCalled();
1821 }
1822 }
1823};
1824
1825// Test InputFilter for MotionEvent
1826TEST_F(InputFilterTest, MotionEvent_InputFilter) {
1827 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
1828 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1829 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1830
1831 // Enable InputFilter
1832 mDispatcher->setInputFilterEnabled(true);
1833 // Test touch on both primary and second display, and check if both events are filtered.
1834 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
1835 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
1836
1837 // Disable InputFilter
1838 mDispatcher->setInputFilterEnabled(false);
1839 // Test touch on both primary and second display, and check if both events aren't filtered.
1840 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1841 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1842}
1843
1844// Test InputFilter for KeyEvent
1845TEST_F(InputFilterTest, KeyEvent_InputFilter) {
1846 // Since the InputFilter is disabled by default, check if key event aren't filtered.
1847 testNotifyKey(/*expectToBeFiltered*/ false);
1848
1849 // Enable InputFilter
1850 mDispatcher->setInputFilterEnabled(true);
1851 // Send a key event, and check if it is filtered.
1852 testNotifyKey(/*expectToBeFiltered*/ true);
1853
1854 // Disable InputFilter
1855 mDispatcher->setInputFilterEnabled(false);
1856 // Send a key event, and check if it isn't filtered.
1857 testNotifyKey(/*expectToBeFiltered*/ false);
1858}
1859
chaviwfd6d3512019-03-25 13:23:49 -07001860class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001861 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07001862 InputDispatcherTest::SetUp();
1863
1864 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1865 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
1866 ADISPLAY_ID_DEFAULT);
1867 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1868 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1869 // window.
1870 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1871
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001872 mFocusedWindow =
1873 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1874 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
1875 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07001876
1877 // Set focused application.
1878 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001879 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07001880
1881 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001882 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001883 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07001884 }
1885
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001886 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07001887 InputDispatcherTest::TearDown();
1888
1889 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001890 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07001891 }
1892
1893protected:
1894 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001895 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001896 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07001897};
1898
1899// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1900// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
1901// the onPointerDownOutsideFocus callback.
1902TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001903 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1904 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1905 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07001906 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07001907 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07001908
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001909 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07001910 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
1911}
1912
1913// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
1914// DOWN on the window that doesn't have focus. Ensure no window received the
1915// onPointerDownOutsideFocus callback.
1916TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001917 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1918 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07001919 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07001920 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07001921
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001922 ASSERT_TRUE(mDispatcher->waitForIdle());
1923 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001924}
1925
1926// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
1927// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
1928TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
1929 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1930 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07001931 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07001932
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001933 ASSERT_TRUE(mDispatcher->waitForIdle());
1934 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001935}
1936
1937// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
1938// DOWN on the window that already has focus. Ensure no window received the
1939// onPointerDownOutsideFocus callback.
1940TEST_F(InputDispatcherOnPointerDownOutsideFocus,
1941 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001942 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1943 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001944 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07001945 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07001946 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07001947
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001948 ASSERT_TRUE(mDispatcher->waitForIdle());
1949 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07001950}
1951
chaviwaf87b3e2019-10-01 16:59:28 -07001952// These tests ensures we can send touch events to a single client when there are multiple input
1953// windows that point to the same client token.
1954class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
1955 virtual void SetUp() override {
1956 InputDispatcherTest::SetUp();
1957
1958 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1959 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
1960 ADISPLAY_ID_DEFAULT);
1961 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
1962 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
1963 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1964 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07001965 mWindow1->setFrame(Rect(0, 0, 100, 100));
1966
1967 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
1968 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
1969 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
1970 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07001971 mWindow2->setFrame(Rect(100, 100, 200, 200));
1972
Arthur Hung72d8dc32020-03-28 00:48:39 +00001973 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07001974 }
1975
1976protected:
1977 sp<FakeWindowHandle> mWindow1;
1978 sp<FakeWindowHandle> mWindow2;
1979
1980 // Helper function to convert the point from screen coordinates into the window's space
1981 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
1982 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
1983 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
1984 return {x, y};
1985 }
1986
1987 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
1988 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001989 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07001990 InputEvent* event = window->consume();
1991
1992 ASSERT_NE(nullptr, event) << name.c_str()
1993 << ": consumer should have returned non-NULL event.";
1994
1995 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
1996 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
1997 << " event, got " << inputEventTypeToString(event->getType()) << " event";
1998
1999 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2000 EXPECT_EQ(expectedAction, motionEvent.getAction());
2001
2002 for (size_t i = 0; i < points.size(); i++) {
2003 float expectedX = points[i].x;
2004 float expectedY = points[i].y;
2005
2006 EXPECT_EQ(expectedX, motionEvent.getX(i))
2007 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2008 << ", got " << motionEvent.getX(i);
2009 EXPECT_EQ(expectedY, motionEvent.getY(i))
2010 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2011 << ", got " << motionEvent.getY(i);
2012 }
2013 }
2014};
2015
2016TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2017 // Touch Window 1
2018 PointF touchedPoint = {10, 10};
2019 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2020
2021 NotifyMotionArgs motionArgs =
2022 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2023 ADISPLAY_ID_DEFAULT, {touchedPoint});
2024 mDispatcher->notifyMotion(&motionArgs);
2025 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2026
2027 // Release touch on Window 1
2028 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2029 ADISPLAY_ID_DEFAULT, {touchedPoint});
2030 mDispatcher->notifyMotion(&motionArgs);
2031 // consume the UP event
2032 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2033
2034 // Touch Window 2
2035 touchedPoint = {150, 150};
2036 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2037
2038 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2039 ADISPLAY_ID_DEFAULT, {touchedPoint});
2040 mDispatcher->notifyMotion(&motionArgs);
2041
2042 // Consuming from window1 since it's the window that has the InputReceiver
2043 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2044}
2045
2046TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
2047 mWindow2->setWindowScale(0.5f, 0.5f);
2048
2049 // Touch Window 1
2050 PointF touchedPoint = {10, 10};
2051 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2052
2053 NotifyMotionArgs motionArgs =
2054 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2055 ADISPLAY_ID_DEFAULT, {touchedPoint});
2056 mDispatcher->notifyMotion(&motionArgs);
2057 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2058
2059 // Release touch on Window 1
2060 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2061 ADISPLAY_ID_DEFAULT, {touchedPoint});
2062 mDispatcher->notifyMotion(&motionArgs);
2063 // consume the UP event
2064 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2065
2066 // Touch Window 2
2067 touchedPoint = {150, 150};
2068 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2069
2070 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2071 ADISPLAY_ID_DEFAULT, {touchedPoint});
2072 mDispatcher->notifyMotion(&motionArgs);
2073
2074 // Consuming from window1 since it's the window that has the InputReceiver
2075 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2076}
2077
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002078TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
2079 mWindow2->setWindowScale(0.5f, 0.5f);
2080
2081 // Touch Window 1
2082 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2083 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2084
2085 NotifyMotionArgs motionArgs =
2086 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2087 ADISPLAY_ID_DEFAULT, touchedPoints);
2088 mDispatcher->notifyMotion(&motionArgs);
2089 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2090
2091 // Touch Window 2
2092 int32_t actionPointerDown =
2093 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2094 touchedPoints.emplace_back(PointF{150, 150});
2095 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2096
2097 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2098 ADISPLAY_ID_DEFAULT, touchedPoints);
2099 mDispatcher->notifyMotion(&motionArgs);
2100
2101 // Consuming from window1 since it's the window that has the InputReceiver
2102 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2103}
2104
2105TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
2106 mWindow2->setWindowScale(0.5f, 0.5f);
2107
2108 // Touch Window 1
2109 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2110 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2111
2112 NotifyMotionArgs motionArgs =
2113 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2114 ADISPLAY_ID_DEFAULT, touchedPoints);
2115 mDispatcher->notifyMotion(&motionArgs);
2116 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2117
2118 // Touch Window 2
2119 int32_t actionPointerDown =
2120 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2121 touchedPoints.emplace_back(PointF{150, 150});
2122 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2123
2124 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2125 ADISPLAY_ID_DEFAULT, touchedPoints);
2126 mDispatcher->notifyMotion(&motionArgs);
2127
2128 // Consuming from window1 since it's the window that has the InputReceiver
2129 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2130
2131 // Move both windows
2132 touchedPoints = {{20, 20}, {175, 175}};
2133 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2134 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2135
2136 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2137 ADISPLAY_ID_DEFAULT, touchedPoints);
2138 mDispatcher->notifyMotion(&motionArgs);
2139
2140 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2141}
2142
2143TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2144 mWindow1->setWindowScale(0.5f, 0.5f);
2145
2146 // Touch Window 1
2147 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2148 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2149
2150 NotifyMotionArgs motionArgs =
2151 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2152 ADISPLAY_ID_DEFAULT, touchedPoints);
2153 mDispatcher->notifyMotion(&motionArgs);
2154 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2155
2156 // Touch Window 2
2157 int32_t actionPointerDown =
2158 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2159 touchedPoints.emplace_back(PointF{150, 150});
2160 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2161
2162 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2163 ADISPLAY_ID_DEFAULT, touchedPoints);
2164 mDispatcher->notifyMotion(&motionArgs);
2165
2166 // Consuming from window1 since it's the window that has the InputReceiver
2167 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2168
2169 // Move both windows
2170 touchedPoints = {{20, 20}, {175, 175}};
2171 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2172 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2173
2174 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2175 ADISPLAY_ID_DEFAULT, touchedPoints);
2176 mDispatcher->notifyMotion(&motionArgs);
2177
2178 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2179}
2180
Garfield Tane84e6f92019-08-29 17:28:41 -07002181} // namespace android::inputdispatcher