blob: 13e835427f6a01b0199ec5acd7f273ca24f8f51b [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>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070020#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070021#include <binder/Binder.h>
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -080022#include <input/Input.h>
Robert Carr803535b2018-08-02 16:38:15 -070023
Michael Wrightd02c5b62014-02-10 15:10:22 -080024#include <gtest/gtest.h>
25#include <linux/input.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080029#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031using android::base::StringPrintf;
32
Garfield Tane84e6f92019-08-29 17:28:41 -070033namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080034
35// An arbitrary time value.
36static const nsecs_t ARBITRARY_TIME = 1234;
37
38// An arbitrary device id.
39static const int32_t DEVICE_ID = 1;
40
Jeff Brownf086ddb2014-02-11 14:28:48 -080041// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080042static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080043
Michael Wrightd02c5b62014-02-10 15:10:22 -080044// An arbitrary injector pid / uid pair that has permission to inject events.
45static const int32_t INJECTOR_PID = 999;
46static const int32_t INJECTOR_UID = 1001;
47
chaviwd1c23182019-12-20 18:44:56 -080048struct PointF {
49 float x;
50 float y;
51};
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
Gang Wang342c9272020-01-13 13:15:04 -050053/**
54 * Return a DOWN key event with KEYCODE_A.
55 */
56static KeyEvent getTestKeyEvent() {
57 KeyEvent event;
58
Garfield Tanfbe732e2020-01-24 11:26:14 -080059 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
60 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
61 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050062 return event;
63}
64
Michael Wrightd02c5b62014-02-10 15:10:22 -080065// --- FakeInputDispatcherPolicy ---
66
67class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
68 InputDispatcherConfiguration mConfig;
69
70protected:
71 virtual ~FakeInputDispatcherPolicy() {
72 }
73
74public:
75 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080076 }
77
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080078 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080079 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
80 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080081 }
82
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080083 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080084 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
85 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080086 }
87
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070088 void assertFilterInputEventWasNotCalled() {
89 std::scoped_lock lock(mLock);
90 ASSERT_EQ(nullptr, mFilteredEvent);
91 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080092
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080093 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070094 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080095 ASSERT_TRUE(mConfigurationChangedTime)
96 << "Timed out waiting for configuration changed call";
97 ASSERT_EQ(*mConfigurationChangedTime, when);
98 mConfigurationChangedTime = std::nullopt;
99 }
100
101 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700102 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800103 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800104 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800105 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
106 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
107 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
108 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
109 mLastNotifySwitch = std::nullopt;
110 }
111
chaviwfd6d3512019-03-25 13:23:49 -0700112 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700113 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800114 ASSERT_EQ(touchedToken, mOnPointerDownToken);
115 mOnPointerDownToken.clear();
116 }
117
118 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700119 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800120 ASSERT_TRUE(mOnPointerDownToken == nullptr)
121 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700122 }
123
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700124 // This function must be called soon after the expected ANR timer starts,
125 // because we are also checking how much time has passed.
126 void assertNotifyAnrWasCalled(std::chrono::nanoseconds timeout,
127 const sp<InputApplicationHandle>& expectedApplication,
128 const sp<IBinder>& expectedToken) {
129 const std::chrono::time_point start = std::chrono::steady_clock::now();
130 std::unique_lock lock(mLock);
131 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
132 android::base::ScopedLockAssertion assumeLocked(mLock);
133
134 // If there is an ANR, Dispatcher won't be idle because there are still events
135 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
136 // before checking if ANR was called.
137 // Since dispatcher is not guaranteed to call notifyAnr right away, we need to provide
138 // it some time to act. 100ms seems reasonable.
139 mNotifyAnr.wait_for(lock, timeToWait,
140 [this]() REQUIRES(mLock) { return mNotifyAnrWasCalled; });
141 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
142 ASSERT_TRUE(mNotifyAnrWasCalled);
143 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
144 // the dispatcher started counting before this function was called
145 ASSERT_TRUE(timeout - 100ms < waited); // check (waited < timeout + 100ms) done by wait_for
146 mNotifyAnrWasCalled = false;
147 ASSERT_EQ(expectedApplication, mLastAnrApplication);
148 ASSERT_EQ(expectedToken, mLastAnrWindowToken);
149 }
150
Garfield Tan1c7bc862020-01-28 13:24:04 -0800151 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
152 mConfig.keyRepeatTimeout = timeout;
153 mConfig.keyRepeatDelay = delay;
154 }
155
Michael Wrightd02c5b62014-02-10 15:10:22 -0800156private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700157 std::mutex mLock;
158 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
159 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
160 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
161 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800162
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700163 // ANR handling
164 bool mNotifyAnrWasCalled GUARDED_BY(mLock) = false;
165 sp<InputApplicationHandle> mLastAnrApplication GUARDED_BY(mLock);
166 sp<IBinder> mLastAnrWindowToken GUARDED_BY(mLock);
167 std::condition_variable mNotifyAnr;
168 std::chrono::nanoseconds mAnrTimeout = 0ms;
169
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800170 virtual void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700171 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800172 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800173 }
174
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700175 virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>& application,
176 const sp<IBinder>& windowToken, const std::string&) override {
177 std::scoped_lock lock(mLock);
178 mLastAnrApplication = application;
179 mLastAnrWindowToken = windowToken;
180 mNotifyAnrWasCalled = true;
181 mNotifyAnr.notify_all();
182 return mAnrTimeout.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800183 }
184
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700185 virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800186
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700187 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700188
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700189 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800190 *outConfig = mConfig;
191 }
192
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800193 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700194 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800195 switch (inputEvent->getType()) {
196 case AINPUT_EVENT_TYPE_KEY: {
197 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800198 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800199 break;
200 }
201
202 case AINPUT_EVENT_TYPE_MOTION: {
203 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800204 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800205 break;
206 }
207 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208 return true;
209 }
210
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700211 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800212
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700213 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800214
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700215 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
216 uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800217 return 0;
218 }
219
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700220 virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
221 KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800222 return false;
223 }
224
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800225 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
226 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700227 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800228 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
229 * essentially a passthrough for notifySwitch.
230 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800231 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800232 }
233
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700234 virtual void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800235
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700236 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800237 return false;
238 }
Jackal Guof9696682018-10-05 12:23:23 +0800239
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700240 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700241 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700242 mOnPointerDownToken = newToken;
243 }
244
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800245 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
246 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700247 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800248 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
249 ASSERT_EQ(mFilteredEvent->getType(), type);
250
251 if (type == AINPUT_EVENT_TYPE_KEY) {
252 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
253 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
254 EXPECT_EQ(keyEvent.getAction(), action);
255 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
256 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
257 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
258 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
259 EXPECT_EQ(motionEvent.getAction(), action);
260 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
261 } else {
262 FAIL() << "Unknown type: " << type;
263 }
264
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800265 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800266 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800267};
268
Gang Wang342c9272020-01-13 13:15:04 -0500269// --- HmacKeyManagerTest ---
270
271class HmacKeyManagerTest : public testing::Test {
272protected:
273 HmacKeyManager mHmacKeyManager;
274};
275
276/**
277 * Ensure that separate calls to sign the same data are generating the same key.
278 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
279 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
280 * tests.
281 */
282TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
283 KeyEvent event = getTestKeyEvent();
284 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
285
286 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
287 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
288 ASSERT_EQ(hmac1, hmac2);
289}
290
291/**
292 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
293 */
294TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
295 KeyEvent event = getTestKeyEvent();
296 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
297 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
298
299 verifiedEvent.deviceId += 1;
300 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
301
302 verifiedEvent.source += 1;
303 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
304
305 verifiedEvent.eventTimeNanos += 1;
306 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
307
308 verifiedEvent.displayId += 1;
309 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
310
311 verifiedEvent.action += 1;
312 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
313
314 verifiedEvent.downTimeNanos += 1;
315 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
316
317 verifiedEvent.flags += 1;
318 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
319
320 verifiedEvent.keyCode += 1;
321 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
322
323 verifiedEvent.scanCode += 1;
324 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
325
326 verifiedEvent.metaState += 1;
327 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
328
329 verifiedEvent.repeatCount += 1;
330 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
331}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800332
333// --- InputDispatcherTest ---
334
335class InputDispatcherTest : public testing::Test {
336protected:
337 sp<FakeInputDispatcherPolicy> mFakePolicy;
338 sp<InputDispatcher> mDispatcher;
339
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700340 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800341 mFakePolicy = new FakeInputDispatcherPolicy();
342 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800343 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
344 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700345 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800346 }
347
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700348 virtual void TearDown() override {
349 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800350 mFakePolicy.clear();
351 mDispatcher.clear();
352 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700353
354 /**
355 * Used for debugging when writing the test
356 */
357 void dumpDispatcherState() {
358 std::string dump;
359 mDispatcher->dump(dump);
360 std::stringstream ss(dump);
361 std::string to;
362
363 while (std::getline(ss, to, '\n')) {
364 ALOGE("%s", to.c_str());
365 }
366 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800367};
368
369
370TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
371 KeyEvent event;
372
373 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800374 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
375 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600376 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
377 ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700378 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
379 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
380 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800381 << "Should reject key events with undefined action.";
382
383 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800384 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
385 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600386 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700387 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
388 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
389 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800390 << "Should reject key events with ACTION_MULTIPLE.";
391}
392
393TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
394 MotionEvent event;
395 PointerProperties pointerProperties[MAX_POINTERS + 1];
396 PointerCoords pointerCoords[MAX_POINTERS + 1];
397 for (int i = 0; i <= MAX_POINTERS; i++) {
398 pointerProperties[i].clear();
399 pointerProperties[i].id = i;
400 pointerCoords[i].clear();
401 }
402
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800403 // Some constants commonly used below
404 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
405 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
406 constexpr int32_t metaState = AMETA_NONE;
407 constexpr MotionClassification classification = MotionClassification::NONE;
408
Michael Wrightd02c5b62014-02-10 15:10:22 -0800409 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800410 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600411 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
412 1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
413 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700414 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700415 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
416 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
417 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800418 << "Should reject motion events with undefined action.";
419
420 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800421 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700422 AMOTION_EVENT_ACTION_POINTER_DOWN |
423 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600424 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
425 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
426 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700427 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700428 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
429 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
430 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800431 << "Should reject motion events with pointer down index too large.";
432
Garfield Tanfbe732e2020-01-24 11:26:14 -0800433 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700434 AMOTION_EVENT_ACTION_POINTER_DOWN |
435 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600436 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
437 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
438 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700439 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700440 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
441 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
442 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800443 << "Should reject motion events with pointer down index too small.";
444
445 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800446 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700447 AMOTION_EVENT_ACTION_POINTER_UP |
448 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600449 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
450 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
451 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700452 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700453 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
454 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
455 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800456 << "Should reject motion events with pointer up index too large.";
457
Garfield Tanfbe732e2020-01-24 11:26:14 -0800458 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700459 AMOTION_EVENT_ACTION_POINTER_UP |
460 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600461 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
462 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
463 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700464 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700465 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
466 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
467 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800468 << "Should reject motion events with pointer up index too small.";
469
470 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800471 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
472 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
473 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
474 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
475 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700476 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700477 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
478 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
479 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800480 << "Should reject motion events with 0 pointers.";
481
Garfield Tanfbe732e2020-01-24 11:26:14 -0800482 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
483 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
484 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
485 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
486 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700487 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700488 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
489 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
490 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800491 << "Should reject motion events with more than MAX_POINTERS pointers.";
492
493 // Rejects motion events with invalid pointer ids.
494 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800495 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
496 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
497 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
498 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
499 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700500 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700501 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
502 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
503 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 << "Should reject motion events with pointer ids less than 0.";
505
506 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800507 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
508 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
509 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
510 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
511 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700512 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700513 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
514 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
515 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800516 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
517
518 // Rejects motion events with duplicate pointer ids.
519 pointerProperties[0].id = 1;
520 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800521 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
522 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
523 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
524 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
525 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700526 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700527 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
528 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
529 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800530 << "Should reject motion events with duplicate pointer ids.";
531}
532
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800533/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
534
535TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
536 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800537 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800538 mDispatcher->notifyConfigurationChanged(&args);
539 ASSERT_TRUE(mDispatcher->waitForIdle());
540
541 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
542}
543
544TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800545 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
546 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800547 mDispatcher->notifySwitch(&args);
548
549 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
550 args.policyFlags |= POLICY_FLAG_TRUSTED;
551 mFakePolicy->assertNotifySwitchWasCalled(args);
552}
553
Arthur Hungb92218b2018-08-14 12:00:21 +0800554// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700555static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700556static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800557
558class FakeApplicationHandle : public InputApplicationHandle {
559public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700560 FakeApplicationHandle() {
561 mInfo.name = "Fake Application";
562 mInfo.token = new BBinder();
563 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
564 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800565 virtual ~FakeApplicationHandle() {}
566
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700567 virtual bool updateInfo() override {
Arthur Hungb92218b2018-08-14 12:00:21 +0800568 return true;
569 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700570
571 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
572 mInfo.dispatchingTimeout = timeout.count();
573 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800574};
575
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800576class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800577public:
chaviwd1c23182019-12-20 18:44:56 -0800578 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
579 : mName(name) {
580 mConsumer = std::make_unique<InputConsumer>(clientChannel);
581 }
582
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800583 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700584 InputEvent* event;
585 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
586 if (!consumeSeq) {
587 return nullptr;
588 }
589 finishEvent(*consumeSeq);
590 return event;
591 }
592
593 /**
594 * Receive an event without acknowledging it.
595 * Return the sequence number that could later be used to send finished signal.
596 */
597 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800598 uint32_t consumeSeq;
599 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800600
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800601 std::chrono::time_point start = std::chrono::steady_clock::now();
602 status_t status = WOULD_BLOCK;
603 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800604 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800605 &event);
606 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
607 if (elapsed > 100ms) {
608 break;
609 }
610 }
611
612 if (status == WOULD_BLOCK) {
613 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700614 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800615 }
616
617 if (status != OK) {
618 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700619 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800620 }
621 if (event == nullptr) {
622 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700623 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800624 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700625 if (outEvent != nullptr) {
626 *outEvent = event;
627 }
628 return consumeSeq;
629 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800630
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700631 /**
632 * To be used together with "receiveEvent" to complete the consumption of an event.
633 */
634 void finishEvent(uint32_t consumeSeq) {
635 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
636 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800637 }
638
639 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
640 int32_t expectedFlags) {
641 InputEvent* event = consume();
642
643 ASSERT_NE(nullptr, event) << mName.c_str()
644 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800645 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800646 << mName.c_str() << "expected " << inputEventTypeToString(expectedEventType)
647 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800648
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800649 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800650
Tiger Huang8664f8c2018-10-11 19:14:35 +0800651 switch (expectedEventType) {
652 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800653 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
654 EXPECT_EQ(expectedAction, keyEvent.getAction());
655 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800656 break;
657 }
658 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800659 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
660 EXPECT_EQ(expectedAction, motionEvent.getAction());
661 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800662 break;
663 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100664 case AINPUT_EVENT_TYPE_FOCUS: {
665 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
666 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800667 default: {
668 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
669 }
670 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800671 }
672
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100673 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
674 InputEvent* event = consume();
675 ASSERT_NE(nullptr, event) << mName.c_str()
676 << ": consumer should have returned non-NULL event.";
677 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
678 << "Got " << inputEventTypeToString(event->getType())
679 << " event instead of FOCUS event";
680
681 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
682 << mName.c_str() << ": event displayId should always be NONE.";
683
684 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
685 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
686 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
687 }
688
chaviwd1c23182019-12-20 18:44:56 -0800689 void assertNoEvents() {
690 InputEvent* event = consume();
691 ASSERT_EQ(nullptr, event)
692 << mName.c_str()
693 << ": should not have received any events, so consume() should return NULL";
694 }
695
696 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
697
698protected:
699 std::unique_ptr<InputConsumer> mConsumer;
700 PreallocatedInputEventFactory mEventFactory;
701
702 std::string mName;
703};
704
705class FakeWindowHandle : public InputWindowHandle {
706public:
707 static const int32_t WIDTH = 600;
708 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800709
710 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
711 const sp<InputDispatcher>& dispatcher, const std::string name,
712 int32_t displayId, sp<IBinder> token = nullptr)
713 : mName(name) {
714 if (token == nullptr) {
715 sp<InputChannel> serverChannel, clientChannel;
716 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
717 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
718 dispatcher->registerInputChannel(serverChannel);
719 token = serverChannel->getConnectionToken();
720 }
721
722 inputApplicationHandle->updateInfo();
723 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
724
725 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700726 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800727 mInfo.name = name;
728 mInfo.layoutParamsFlags = 0;
729 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700730 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
chaviwd1c23182019-12-20 18:44:56 -0800731 mInfo.frameLeft = 0;
732 mInfo.frameTop = 0;
733 mInfo.frameRight = WIDTH;
734 mInfo.frameBottom = HEIGHT;
735 mInfo.globalScaleFactor = 1.0;
736 mInfo.touchableRegion.clear();
737 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
738 mInfo.visible = true;
739 mInfo.canReceiveKeys = true;
740 mInfo.hasFocus = false;
741 mInfo.hasWallpaper = false;
742 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800743 mInfo.ownerPid = INJECTOR_PID;
744 mInfo.ownerUid = INJECTOR_UID;
745 mInfo.inputFeatures = 0;
746 mInfo.displayId = displayId;
747 }
748
749 virtual bool updateInfo() { return true; }
750
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100751 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800752
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700753 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
754 mInfo.dispatchingTimeout = timeout.count();
755 }
756
chaviwd1c23182019-12-20 18:44:56 -0800757 void setFrame(const Rect& frame) {
758 mInfo.frameLeft = frame.left;
759 mInfo.frameTop = frame.top;
760 mInfo.frameRight = frame.right;
761 mInfo.frameBottom = frame.bottom;
762 mInfo.touchableRegion.clear();
763 mInfo.addTouchableRegion(frame);
764 }
765
766 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
767
chaviwaf87b3e2019-10-01 16:59:28 -0700768 void setWindowScale(float xScale, float yScale) {
769 mInfo.windowXScale = xScale;
770 mInfo.windowYScale = yScale;
771 }
772
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800773 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
774 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
775 expectedFlags);
776 }
777
Svet Ganov5d3bc372020-01-26 23:11:07 -0800778 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
779 int32_t expectedFlags = 0) {
780 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
781 expectedFlags);
782 }
783
784 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
785 int32_t expectedFlags = 0) {
786 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
787 expectedFlags);
788 }
789
790 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
791 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800792 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
793 expectedFlags);
794 }
795
Svet Ganov5d3bc372020-01-26 23:11:07 -0800796 void consumeMotionPointerDown(int32_t pointerIdx,
797 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
798 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
799 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
800 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
801 }
802
803 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
804 int32_t expectedFlags = 0) {
805 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
806 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
807 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
808 }
809
810 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
811 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000812 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
813 expectedFlags);
814 }
815
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100816 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
817 ASSERT_NE(mInputReceiver, nullptr)
818 << "Cannot consume events from a window with no receiver";
819 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
820 }
821
chaviwd1c23182019-12-20 18:44:56 -0800822 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
823 int32_t expectedFlags) {
824 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
825 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
826 expectedFlags);
827 }
828
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700829 std::optional<uint32_t> receiveEvent() {
830 if (mInputReceiver == nullptr) {
831 ADD_FAILURE() << "Invalid receive event on window with no receiver";
832 return std::nullopt;
833 }
834 return mInputReceiver->receiveEvent();
835 }
836
837 void finishEvent(uint32_t sequenceNum) {
838 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
839 mInputReceiver->finishEvent(sequenceNum);
840 }
841
chaviwaf87b3e2019-10-01 16:59:28 -0700842 InputEvent* consume() {
843 if (mInputReceiver == nullptr) {
844 return nullptr;
845 }
846 return mInputReceiver->consume();
847 }
848
Arthur Hungb92218b2018-08-14 12:00:21 +0800849 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800850 ASSERT_NE(mInputReceiver, nullptr)
851 << "Call 'assertNoEvents' on a window with an InputReceiver";
852 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800853 }
854
chaviwaf87b3e2019-10-01 16:59:28 -0700855 sp<IBinder> getToken() { return mInfo.token; }
856
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100857 const std::string& getName() { return mName; }
858
chaviwd1c23182019-12-20 18:44:56 -0800859private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100860 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800861 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700862 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800863};
864
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700865std::atomic<int32_t> FakeWindowHandle::sId{1};
866
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700867static int32_t injectKey(const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
868 int32_t displayId = ADISPLAY_ID_NONE) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800869 KeyEvent event;
870 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
871
872 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800873 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700874 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
875 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800876
877 // Inject event until dispatch out.
878 return dispatcher->injectInputEvent(
879 &event,
880 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
881 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
882}
883
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
885 int32_t displayId = ADISPLAY_ID_NONE) {
886 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
887}
888
889static int32_t injectMotionEvent(
890 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
891 const PointF& position,
892 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
893 AMOTION_EVENT_INVALID_CURSOR_POSITION}) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800894 MotionEvent event;
895 PointerProperties pointerProperties[1];
896 PointerCoords pointerCoords[1];
897
898 pointerProperties[0].clear();
899 pointerProperties[0].id = 0;
900 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
901
902 pointerCoords[0].clear();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700903 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, position.x);
904 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, position.y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800905
906 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
907 // Define a valid motion down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800908 event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
909 /* actionButton */ 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600910 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700911 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600912 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700913 /* xPrecision */ 0, /* yPrecision */ 0, cursorPosition.x, cursorPosition.y,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600914 currentTime, currentTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700915 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800916
917 // Inject event until dispatch out.
918 return dispatcher->injectInputEvent(
919 &event,
920 INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
921 INJECT_EVENT_TIMEOUT, POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
922}
923
Garfield Tan00f511d2019-06-12 16:55:40 -0700924static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700925 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700926 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700927}
928
Michael Wright3a240c42019-12-10 20:53:41 +0000929static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700930 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700931 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000932}
933
Jackal Guof9696682018-10-05 12:23:23 +0800934static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
935 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
936 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800937 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
938 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
939 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800940
941 return args;
942}
943
chaviwd1c23182019-12-20 18:44:56 -0800944static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
945 const std::vector<PointF>& points) {
946 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700947 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
948 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
949 }
950
chaviwd1c23182019-12-20 18:44:56 -0800951 PointerProperties pointerProperties[pointerCount];
952 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800953
chaviwd1c23182019-12-20 18:44:56 -0800954 for (size_t i = 0; i < pointerCount; i++) {
955 pointerProperties[i].clear();
956 pointerProperties[i].id = i;
957 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800958
chaviwd1c23182019-12-20 18:44:56 -0800959 pointerCoords[i].clear();
960 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
961 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
962 }
Jackal Guof9696682018-10-05 12:23:23 +0800963
964 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
965 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800966 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -0700967 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
968 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800969 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
970 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700971 AMOTION_EVENT_INVALID_CURSOR_POSITION,
972 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +0800973
974 return args;
975}
976
chaviwd1c23182019-12-20 18:44:56 -0800977static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
978 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
979}
980
Arthur Hungb92218b2018-08-14 12:00:21 +0800981TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
982 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800983 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
984 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800985
Arthur Hung72d8dc32020-03-28 00:48:39 +0000986 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800987 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
988 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +0800989 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
990
991 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800992 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800993}
994
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700995/**
996 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
997 * To ensure that window receives only events that were directly inside of it, add
998 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
999 * when finding touched windows.
1000 * This test serves as a sanity check for the next test, where setInputWindows is
1001 * called twice.
1002 */
1003TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
1004 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1005 sp<FakeWindowHandle> window =
1006 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1007 window->setFrame(Rect(0, 0, 100, 100));
1008 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1009
1010 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1011 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1012 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1013 {50, 50}))
1014 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1015
1016 // Window should receive motion event.
1017 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1018}
1019
1020/**
1021 * Calling setInputWindows twice, with the same info, should not cause any issues.
1022 * To ensure that window receives only events that were directly inside of it, add
1023 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1024 * when finding touched windows.
1025 */
1026TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
1027 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1028 sp<FakeWindowHandle> window =
1029 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1030 window->setFrame(Rect(0, 0, 100, 100));
1031 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1032
1033 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1034 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1035 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1036 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1037 {50, 50}))
1038 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1039
1040 // Window should receive motion event.
1041 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1042}
1043
Arthur Hungb92218b2018-08-14 12:00:21 +08001044// The foreground window should receive the first touch down event.
1045TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
1046 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001047 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1048 ADISPLAY_ID_DEFAULT);
1049 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1050 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001051
Arthur Hung72d8dc32020-03-28 00:48:39 +00001052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001053 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1054 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001055 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1056
1057 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001058 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001059 windowSecond->assertNoEvents();
1060}
1061
1062TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
1063 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001064 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1065 ADISPLAY_ID_DEFAULT);
1066 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1067 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001068
Arthur Hung7ab76b12019-01-09 19:17:20 +08001069 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +08001070 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +08001071
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001072 // Display should have only one focused window
1073 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001075
1076 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001077 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1078 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1079
1080 // Focused window should receive event.
1081 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001082 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001083}
1084
Arthur Hung7ab76b12019-01-09 19:17:20 +08001085TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
1086 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1087 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1088 ADISPLAY_ID_DEFAULT);
1089 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1090 ADISPLAY_ID_DEFAULT);
1091
1092 // Set focused application.
1093 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1094
1095 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001096 windowTop->setFocus(true);
1097 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001098
Arthur Hung72d8dc32020-03-28 00:48:39 +00001099 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001100 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001101 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1102 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1103
1104 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001105 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001106 windowSecond->assertNoEvents();
1107}
1108
Arthur Hung3b413f22018-10-26 18:05:34 +08001109TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
1110 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1111
1112 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1113 ADISPLAY_ID_DEFAULT);
1114 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1115 ADISPLAY_ID_DEFAULT);
1116
Arthur Hung832bc4a2019-01-28 11:43:17 +08001117 // Set focused application.
1118 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001119
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001120 windowTop->setFocus(true);
1121 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001122 // Release channel for window is no longer valid.
1123 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001124 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001125 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001126
Arthur Hung832bc4a2019-01-28 11:43:17 +08001127 // Test inject a key down, should dispatch to a valid window.
1128 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1129 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001130
1131 // Top window is invalid, so it should not receive any input event.
1132 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001133 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001134}
1135
Garfield Tan00f511d2019-06-12 16:55:40 -07001136TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
1137 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1138
1139 sp<FakeWindowHandle> windowLeft =
1140 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1141 windowLeft->setFrame(Rect(0, 0, 600, 800));
1142 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1143 sp<FakeWindowHandle> windowRight =
1144 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1145 windowRight->setFrame(Rect(600, 0, 1200, 800));
1146 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1147
1148 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1149
Arthur Hung72d8dc32020-03-28 00:48:39 +00001150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001151
1152 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1153 // left window. This event should be dispatched to the left window.
1154 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1155 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001156 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001157 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001158 windowRight->assertNoEvents();
1159}
1160
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001161TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
1162 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1163 sp<FakeWindowHandle> window =
1164 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001165 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001166
Arthur Hung72d8dc32020-03-28 00:48:39 +00001167 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001168 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001169
1170 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1171 mDispatcher->notifyKey(&keyArgs);
1172
1173 // Window should receive key down event.
1174 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1175
1176 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1177 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001178 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001179 mDispatcher->notifyDeviceReset(&args);
1180 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1181 AKEY_EVENT_FLAG_CANCELED);
1182}
1183
1184TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1185 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1186 sp<FakeWindowHandle> window =
1187 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1188
Arthur Hung72d8dc32020-03-28 00:48:39 +00001189 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001190
1191 NotifyMotionArgs motionArgs =
1192 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1193 ADISPLAY_ID_DEFAULT);
1194 mDispatcher->notifyMotion(&motionArgs);
1195
1196 // Window should receive motion down event.
1197 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1198
1199 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1200 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001201 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001202 mDispatcher->notifyDeviceReset(&args);
1203 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1204 0 /*expectedFlags*/);
1205}
1206
Svet Ganov5d3bc372020-01-26 23:11:07 -08001207TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1208 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1209
1210 // Create a couple of windows
1211 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1212 "First Window", ADISPLAY_ID_DEFAULT);
1213 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1214 "Second Window", ADISPLAY_ID_DEFAULT);
1215
1216 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001217 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001218
1219 // Send down to the first window
1220 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1221 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1222 mDispatcher->notifyMotion(&downMotionArgs);
1223 // Only the first window should get the down event
1224 firstWindow->consumeMotionDown();
1225 secondWindow->assertNoEvents();
1226
1227 // Transfer touch focus to the second window
1228 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1229 // The first window gets cancel and the second gets down
1230 firstWindow->consumeMotionCancel();
1231 secondWindow->consumeMotionDown();
1232
1233 // Send up event to the second window
1234 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1235 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1236 mDispatcher->notifyMotion(&upMotionArgs);
1237 // The first window gets no events and the second gets up
1238 firstWindow->assertNoEvents();
1239 secondWindow->consumeMotionUp();
1240}
1241
1242TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1243 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1244
1245 PointF touchPoint = {10, 10};
1246
1247 // Create a couple of windows
1248 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1249 "First Window", ADISPLAY_ID_DEFAULT);
1250 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1251 "Second Window", ADISPLAY_ID_DEFAULT);
1252
1253 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001254 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255
1256 // Send down to the first window
1257 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1258 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1259 mDispatcher->notifyMotion(&downMotionArgs);
1260 // Only the first window should get the down event
1261 firstWindow->consumeMotionDown();
1262 secondWindow->assertNoEvents();
1263
1264 // Send pointer down to the first window
1265 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1266 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1267 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1268 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1269 // Only the first window should get the pointer down event
1270 firstWindow->consumeMotionPointerDown(1);
1271 secondWindow->assertNoEvents();
1272
1273 // Transfer touch focus to the second window
1274 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1275 // The first window gets cancel and the second gets down and pointer down
1276 firstWindow->consumeMotionCancel();
1277 secondWindow->consumeMotionDown();
1278 secondWindow->consumeMotionPointerDown(1);
1279
1280 // Send pointer up to the second window
1281 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1282 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1283 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1284 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1285 // The first window gets nothing and the second gets pointer up
1286 firstWindow->assertNoEvents();
1287 secondWindow->consumeMotionPointerUp(1);
1288
1289 // Send up event to the second window
1290 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1291 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1292 mDispatcher->notifyMotion(&upMotionArgs);
1293 // The first window gets nothing and the second gets up
1294 firstWindow->assertNoEvents();
1295 secondWindow->consumeMotionUp();
1296}
1297
1298TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1299 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1300
1301 // Create a non touch modal window that supports split touch
1302 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1303 "First Window", ADISPLAY_ID_DEFAULT);
1304 firstWindow->setFrame(Rect(0, 0, 600, 400));
1305 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1306 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1307
1308 // Create a non touch modal window that supports split touch
1309 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1310 "Second Window", ADISPLAY_ID_DEFAULT);
1311 secondWindow->setFrame(Rect(0, 400, 600, 800));
1312 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1313 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1314
1315 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001316 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001317
1318 PointF pointInFirst = {300, 200};
1319 PointF pointInSecond = {300, 600};
1320
1321 // Send down to the first window
1322 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1323 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1324 mDispatcher->notifyMotion(&firstDownMotionArgs);
1325 // Only the first window should get the down event
1326 firstWindow->consumeMotionDown();
1327 secondWindow->assertNoEvents();
1328
1329 // Send down to the second window
1330 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1331 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1332 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1333 mDispatcher->notifyMotion(&secondDownMotionArgs);
1334 // The first window gets a move and the second a down
1335 firstWindow->consumeMotionMove();
1336 secondWindow->consumeMotionDown();
1337
1338 // Transfer touch focus to the second window
1339 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1340 // The first window gets cancel and the new gets pointer down (it already saw down)
1341 firstWindow->consumeMotionCancel();
1342 secondWindow->consumeMotionPointerDown(1);
1343
1344 // Send pointer up to the second window
1345 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1346 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1347 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1348 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1349 // The first window gets nothing and the second gets pointer up
1350 firstWindow->assertNoEvents();
1351 secondWindow->consumeMotionPointerUp(1);
1352
1353 // Send up event to the second window
1354 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1355 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1356 mDispatcher->notifyMotion(&upMotionArgs);
1357 // The first window gets nothing and the second gets up
1358 firstWindow->assertNoEvents();
1359 secondWindow->consumeMotionUp();
1360}
1361
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001362TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1363 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1364 sp<FakeWindowHandle> window =
1365 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1366
1367 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001368 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001369
1370 window->consumeFocusEvent(true);
1371
1372 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1373 mDispatcher->notifyKey(&keyArgs);
1374
1375 // Window should receive key down event.
1376 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1377}
1378
1379TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1380 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1381 sp<FakeWindowHandle> window =
1382 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1383
Arthur Hung72d8dc32020-03-28 00:48:39 +00001384 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001385
1386 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1387 mDispatcher->notifyKey(&keyArgs);
1388 mDispatcher->waitForIdle();
1389
1390 window->assertNoEvents();
1391}
1392
1393// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1394TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1395 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1396 sp<FakeWindowHandle> window =
1397 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1398
Arthur Hung72d8dc32020-03-28 00:48:39 +00001399 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001400
1401 // Send key
1402 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1403 mDispatcher->notifyKey(&keyArgs);
1404 // Send motion
1405 NotifyMotionArgs motionArgs =
1406 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1407 ADISPLAY_ID_DEFAULT);
1408 mDispatcher->notifyMotion(&motionArgs);
1409
1410 // Window should receive only the motion event
1411 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1412 window->assertNoEvents(); // Key event or focus event will not be received
1413}
1414
chaviwd1c23182019-12-20 18:44:56 -08001415class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001416public:
1417 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001418 int32_t displayId, bool isGestureMonitor = false) {
1419 sp<InputChannel> serverChannel, clientChannel;
1420 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1421 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1422 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001423 }
1424
chaviwd1c23182019-12-20 18:44:56 -08001425 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1426
1427 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1428 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1429 expectedDisplayId, expectedFlags);
1430 }
1431
1432 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1433 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1434 expectedDisplayId, expectedFlags);
1435 }
1436
1437 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1438 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1439 expectedDisplayId, expectedFlags);
1440 }
1441
1442 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1443
1444private:
1445 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001446};
1447
1448// Tests for gesture monitors
1449TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1450 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1451 sp<FakeWindowHandle> window =
1452 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001454
chaviwd1c23182019-12-20 18:44:56 -08001455 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1456 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001457
1458 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1459 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1460 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1461 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001462 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001463}
1464
1465TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1466 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1467 sp<FakeWindowHandle> window =
1468 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1469
1470 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001471 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001472
Arthur Hung72d8dc32020-03-28 00:48:39 +00001473 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001474 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001475
chaviwd1c23182019-12-20 18:44:56 -08001476 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1477 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001478
1479 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1480 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1481 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001482 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001483}
1484
1485TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1486 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1487 sp<FakeWindowHandle> window =
1488 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001489 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001490
chaviwd1c23182019-12-20 18:44:56 -08001491 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1492 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001493
1494 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1495 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1496 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1497 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001498 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001499
1500 window->releaseChannel();
1501
chaviwd1c23182019-12-20 18:44:56 -08001502 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001503
1504 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1505 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1506 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001507 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001508}
1509
chaviw81e2bb92019-12-18 15:03:51 -08001510TEST_F(InputDispatcherTest, TestMoveEvent) {
1511 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1512 sp<FakeWindowHandle> window =
1513 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1514
Arthur Hung72d8dc32020-03-28 00:48:39 +00001515 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001516
1517 NotifyMotionArgs motionArgs =
1518 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1519 ADISPLAY_ID_DEFAULT);
1520
1521 mDispatcher->notifyMotion(&motionArgs);
1522 // Window should receive motion down event.
1523 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1524
1525 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001526 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001527 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1528 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1529 motionArgs.pointerCoords[0].getX() - 10);
1530
1531 mDispatcher->notifyMotion(&motionArgs);
1532 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1533 0 /*expectedFlags*/);
1534}
1535
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001536/**
1537 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1538 * the device default right away. In the test scenario, we check both the default value,
1539 * and the action of enabling / disabling.
1540 */
1541TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1542 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1543 sp<FakeWindowHandle> window =
1544 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1545
1546 // Set focused application.
1547 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1548 window->setFocus(true);
1549
1550 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001551 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001552 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1553
1554 SCOPED_TRACE("Remove the window to trigger focus loss");
1555 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001556 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001557 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1558
1559 SCOPED_TRACE("Disable touch mode");
1560 mDispatcher->setInTouchMode(false);
1561 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001562 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001563 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1564
1565 SCOPED_TRACE("Remove the window to trigger focus loss");
1566 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001567 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001568 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1569
1570 SCOPED_TRACE("Enable touch mode again");
1571 mDispatcher->setInTouchMode(true);
1572 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001573 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001574 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1575
1576 window->assertNoEvents();
1577}
1578
Gang Wange9087892020-01-07 12:17:14 -05001579TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1580 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1581 sp<FakeWindowHandle> window =
1582 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1583
1584 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1585 window->setFocus(true);
1586
Arthur Hung72d8dc32020-03-28 00:48:39 +00001587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001588 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1589
1590 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1591 mDispatcher->notifyKey(&keyArgs);
1592
1593 InputEvent* event = window->consume();
1594 ASSERT_NE(event, nullptr);
1595
1596 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1597 ASSERT_NE(verified, nullptr);
1598 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1599
1600 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1601 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1602 ASSERT_EQ(keyArgs.source, verified->source);
1603 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1604
1605 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1606
1607 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1608 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001609 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1610 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1611 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1612 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1613 ASSERT_EQ(0, verifiedKey.repeatCount);
1614}
1615
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001616TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
1617 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1618 sp<FakeWindowHandle> window =
1619 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1620
1621 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1622
Arthur Hung72d8dc32020-03-28 00:48:39 +00001623 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001624
1625 NotifyMotionArgs motionArgs =
1626 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1627 ADISPLAY_ID_DEFAULT);
1628 mDispatcher->notifyMotion(&motionArgs);
1629
1630 InputEvent* event = window->consume();
1631 ASSERT_NE(event, nullptr);
1632
1633 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1634 ASSERT_NE(verified, nullptr);
1635 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
1636
1637 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
1638 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
1639 EXPECT_EQ(motionArgs.source, verified->source);
1640 EXPECT_EQ(motionArgs.displayId, verified->displayId);
1641
1642 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
1643
1644 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
1645 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
1646 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
1647 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
1648 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
1649 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
1650 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
1651}
1652
Garfield Tan1c7bc862020-01-28 13:24:04 -08001653class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
1654protected:
1655 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
1656 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
1657
1658 sp<FakeApplicationHandle> mApp;
1659 sp<FakeWindowHandle> mWindow;
1660
1661 virtual void SetUp() override {
1662 mFakePolicy = new FakeInputDispatcherPolicy();
1663 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
1664 mDispatcher = new InputDispatcher(mFakePolicy);
1665 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
1666 ASSERT_EQ(OK, mDispatcher->start());
1667
1668 setUpWindow();
1669 }
1670
1671 void setUpWindow() {
1672 mApp = new FakeApplicationHandle();
1673 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1674
1675 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001676 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08001677
1678 mWindow->consumeFocusEvent(true);
1679 }
1680
1681 void sendAndConsumeKeyDown() {
1682 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1683 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
1684 mDispatcher->notifyKey(&keyArgs);
1685
1686 // Window should receive key down event.
1687 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1688 }
1689
1690 void expectKeyRepeatOnce(int32_t repeatCount) {
1691 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
1692 InputEvent* repeatEvent = mWindow->consume();
1693 ASSERT_NE(nullptr, repeatEvent);
1694
1695 uint32_t eventType = repeatEvent->getType();
1696 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
1697
1698 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
1699 uint32_t eventAction = repeatKeyEvent->getAction();
1700 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
1701 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
1702 }
1703
1704 void sendAndConsumeKeyUp() {
1705 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
1706 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
1707 mDispatcher->notifyKey(&keyArgs);
1708
1709 // Window should receive key down event.
1710 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1711 0 /*expectedFlags*/);
1712 }
1713};
1714
1715TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
1716 sendAndConsumeKeyDown();
1717 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1718 expectKeyRepeatOnce(repeatCount);
1719 }
1720}
1721
1722TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
1723 sendAndConsumeKeyDown();
1724 expectKeyRepeatOnce(1 /*repeatCount*/);
1725 sendAndConsumeKeyUp();
1726 mWindow->assertNoEvents();
1727}
1728
1729TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
1730 sendAndConsumeKeyDown();
1731 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1732 InputEvent* repeatEvent = mWindow->consume();
1733 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1734 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
1735 IdGenerator::getSource(repeatEvent->getId()));
1736 }
1737}
1738
1739TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
1740 sendAndConsumeKeyDown();
1741
1742 std::unordered_set<int32_t> idSet;
1743 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1744 InputEvent* repeatEvent = mWindow->consume();
1745 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1746 int32_t id = repeatEvent->getId();
1747 EXPECT_EQ(idSet.end(), idSet.find(id));
1748 idSet.insert(id);
1749 }
1750}
1751
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001752/* Test InputDispatcher for MultiDisplay */
1753class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1754public:
1755 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001756 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001757 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001758
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001759 application1 = new FakeApplicationHandle();
1760 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1761 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001762
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001763 // Set focus window for primary display, but focused display would be second one.
1764 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001765 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001766 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001767 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001768
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001769 application2 = new FakeApplicationHandle();
1770 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1771 SECOND_DISPLAY_ID);
1772 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001773 // Set focus display to second one.
1774 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1775 // Set focus window for second display.
1776 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001777 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001778 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001779 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001780 }
1781
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001782 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001783 InputDispatcherTest::TearDown();
1784
1785 application1.clear();
1786 windowInPrimary.clear();
1787 application2.clear();
1788 windowInSecondary.clear();
1789 }
1790
1791protected:
1792 sp<FakeApplicationHandle> application1;
1793 sp<FakeWindowHandle> windowInPrimary;
1794 sp<FakeApplicationHandle> application2;
1795 sp<FakeWindowHandle> windowInSecondary;
1796};
1797
1798TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1799 // Test touch down on primary display.
1800 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1801 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001802 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001803 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001804 windowInSecondary->assertNoEvents();
1805
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001806 // Test touch down on second display.
1807 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1808 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001809 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1810 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001811 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001812}
1813
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001814TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001815 // Test inject a key down with display id specified.
1816 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1817 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001818 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001819 windowInSecondary->assertNoEvents();
1820
1821 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001822 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1823 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1824 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001825 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001826
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001827 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001828 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08001829
1830 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001831 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1832 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001833
1834 // Test inject a key down, should timeout because of no target window.
1835 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1836 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1837 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001838 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001839 windowInSecondary->assertNoEvents();
1840}
1841
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001842// Test per-display input monitors for motion event.
1843TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001844 FakeMonitorReceiver monitorInPrimary =
1845 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1846 FakeMonitorReceiver monitorInSecondary =
1847 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001848
1849 // Test touch down on primary display.
1850 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1851 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1852 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001853 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001854 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001855 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001856 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001857
1858 // Test touch down on second display.
1859 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1860 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1861 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1862 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001863 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001864 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001865 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001866
1867 // Test inject a non-pointer motion event.
1868 // If specific a display, it will dispatch to the focused window of particular display,
1869 // or it will dispatch to the focused window of focused display.
1870 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1871 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1872 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1873 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001874 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001875 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001876 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001877}
1878
1879// Test per-display input monitors for key event.
1880TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1881 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001882 FakeMonitorReceiver monitorInPrimary =
1883 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1884 FakeMonitorReceiver monitorInSecondary =
1885 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001886
1887 // Test inject a key down.
1888 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1889 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1890 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001891 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001892 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001893 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001894}
1895
Jackal Guof9696682018-10-05 12:23:23 +08001896class InputFilterTest : public InputDispatcherTest {
1897protected:
1898 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1899
1900 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1901 NotifyMotionArgs motionArgs;
1902
1903 motionArgs = generateMotionArgs(
1904 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1905 mDispatcher->notifyMotion(&motionArgs);
1906 motionArgs = generateMotionArgs(
1907 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1908 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001909 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001910 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001911 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001912 } else {
1913 mFakePolicy->assertFilterInputEventWasNotCalled();
1914 }
1915 }
1916
1917 void testNotifyKey(bool expectToBeFiltered) {
1918 NotifyKeyArgs keyArgs;
1919
1920 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1921 mDispatcher->notifyKey(&keyArgs);
1922 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1923 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001924 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001925
1926 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001927 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001928 } else {
1929 mFakePolicy->assertFilterInputEventWasNotCalled();
1930 }
1931 }
1932};
1933
1934// Test InputFilter for MotionEvent
1935TEST_F(InputFilterTest, MotionEvent_InputFilter) {
1936 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
1937 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1938 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1939
1940 // Enable InputFilter
1941 mDispatcher->setInputFilterEnabled(true);
1942 // Test touch on both primary and second display, and check if both events are filtered.
1943 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
1944 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
1945
1946 // Disable InputFilter
1947 mDispatcher->setInputFilterEnabled(false);
1948 // Test touch on both primary and second display, and check if both events aren't filtered.
1949 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
1950 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
1951}
1952
1953// Test InputFilter for KeyEvent
1954TEST_F(InputFilterTest, KeyEvent_InputFilter) {
1955 // Since the InputFilter is disabled by default, check if key event aren't filtered.
1956 testNotifyKey(/*expectToBeFiltered*/ false);
1957
1958 // Enable InputFilter
1959 mDispatcher->setInputFilterEnabled(true);
1960 // Send a key event, and check if it is filtered.
1961 testNotifyKey(/*expectToBeFiltered*/ true);
1962
1963 // Disable InputFilter
1964 mDispatcher->setInputFilterEnabled(false);
1965 // Send a key event, and check if it isn't filtered.
1966 testNotifyKey(/*expectToBeFiltered*/ false);
1967}
1968
chaviwfd6d3512019-03-25 13:23:49 -07001969class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001970 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07001971 InputDispatcherTest::SetUp();
1972
1973 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1974 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
1975 ADISPLAY_ID_DEFAULT);
1976 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
1977 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
1978 // window.
1979 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1980
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001981 mFocusedWindow =
1982 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
1983 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
1984 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07001985
1986 // Set focused application.
1987 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001988 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07001989
1990 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001992 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07001993 }
1994
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001995 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07001996 InputDispatcherTest::TearDown();
1997
1998 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001999 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002000 }
2001
2002protected:
2003 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002004 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002005 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002006};
2007
2008// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2009// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2010// the onPointerDownOutsideFocus callback.
2011TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002012 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2013 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2014 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002015 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002016 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002017
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002018 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002019 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2020}
2021
2022// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2023// DOWN on the window that doesn't have focus. Ensure no window received the
2024// onPointerDownOutsideFocus callback.
2025TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002026 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2027 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002028 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002029 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002030
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002031 ASSERT_TRUE(mDispatcher->waitForIdle());
2032 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002033}
2034
2035// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2036// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2037TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
2038 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2039 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002040 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002041
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002042 ASSERT_TRUE(mDispatcher->waitForIdle());
2043 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002044}
2045
2046// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2047// DOWN on the window that already has focus. Ensure no window received the
2048// onPointerDownOutsideFocus callback.
2049TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2050 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002051 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2052 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002053 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07002054 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002055 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002056
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002057 ASSERT_TRUE(mDispatcher->waitForIdle());
2058 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002059}
2060
chaviwaf87b3e2019-10-01 16:59:28 -07002061// These tests ensures we can send touch events to a single client when there are multiple input
2062// windows that point to the same client token.
2063class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2064 virtual void SetUp() override {
2065 InputDispatcherTest::SetUp();
2066
2067 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2068 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2069 ADISPLAY_ID_DEFAULT);
2070 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2071 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
2072 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2073 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002074 mWindow1->setFrame(Rect(0, 0, 100, 100));
2075
2076 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2077 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
2078 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2079 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002080 mWindow2->setFrame(Rect(100, 100, 200, 200));
2081
Arthur Hung72d8dc32020-03-28 00:48:39 +00002082 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002083 }
2084
2085protected:
2086 sp<FakeWindowHandle> mWindow1;
2087 sp<FakeWindowHandle> mWindow2;
2088
2089 // Helper function to convert the point from screen coordinates into the window's space
2090 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
2091 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
2092 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
2093 return {x, y};
2094 }
2095
2096 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2097 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002098 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002099 InputEvent* event = window->consume();
2100
2101 ASSERT_NE(nullptr, event) << name.c_str()
2102 << ": consumer should have returned non-NULL event.";
2103
2104 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2105 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2106 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2107
2108 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2109 EXPECT_EQ(expectedAction, motionEvent.getAction());
2110
2111 for (size_t i = 0; i < points.size(); i++) {
2112 float expectedX = points[i].x;
2113 float expectedY = points[i].y;
2114
2115 EXPECT_EQ(expectedX, motionEvent.getX(i))
2116 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2117 << ", got " << motionEvent.getX(i);
2118 EXPECT_EQ(expectedY, motionEvent.getY(i))
2119 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2120 << ", got " << motionEvent.getY(i);
2121 }
2122 }
2123};
2124
2125TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2126 // Touch Window 1
2127 PointF touchedPoint = {10, 10};
2128 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2129
2130 NotifyMotionArgs motionArgs =
2131 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2132 ADISPLAY_ID_DEFAULT, {touchedPoint});
2133 mDispatcher->notifyMotion(&motionArgs);
2134 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2135
2136 // Release touch on Window 1
2137 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2138 ADISPLAY_ID_DEFAULT, {touchedPoint});
2139 mDispatcher->notifyMotion(&motionArgs);
2140 // consume the UP event
2141 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2142
2143 // Touch Window 2
2144 touchedPoint = {150, 150};
2145 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2146
2147 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2148 ADISPLAY_ID_DEFAULT, {touchedPoint});
2149 mDispatcher->notifyMotion(&motionArgs);
2150
2151 // Consuming from window1 since it's the window that has the InputReceiver
2152 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2153}
2154
2155TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
2156 mWindow2->setWindowScale(0.5f, 0.5f);
2157
2158 // Touch Window 1
2159 PointF touchedPoint = {10, 10};
2160 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2161
2162 NotifyMotionArgs motionArgs =
2163 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2164 ADISPLAY_ID_DEFAULT, {touchedPoint});
2165 mDispatcher->notifyMotion(&motionArgs);
2166 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2167
2168 // Release touch on Window 1
2169 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2170 ADISPLAY_ID_DEFAULT, {touchedPoint});
2171 mDispatcher->notifyMotion(&motionArgs);
2172 // consume the UP event
2173 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2174
2175 // Touch Window 2
2176 touchedPoint = {150, 150};
2177 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2178
2179 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2180 ADISPLAY_ID_DEFAULT, {touchedPoint});
2181 mDispatcher->notifyMotion(&motionArgs);
2182
2183 // Consuming from window1 since it's the window that has the InputReceiver
2184 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2185}
2186
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002187TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
2188 mWindow2->setWindowScale(0.5f, 0.5f);
2189
2190 // Touch Window 1
2191 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2192 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2193
2194 NotifyMotionArgs motionArgs =
2195 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2196 ADISPLAY_ID_DEFAULT, touchedPoints);
2197 mDispatcher->notifyMotion(&motionArgs);
2198 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2199
2200 // Touch Window 2
2201 int32_t actionPointerDown =
2202 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2203 touchedPoints.emplace_back(PointF{150, 150});
2204 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2205
2206 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2207 ADISPLAY_ID_DEFAULT, touchedPoints);
2208 mDispatcher->notifyMotion(&motionArgs);
2209
2210 // Consuming from window1 since it's the window that has the InputReceiver
2211 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2212}
2213
2214TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
2215 mWindow2->setWindowScale(0.5f, 0.5f);
2216
2217 // Touch Window 1
2218 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2219 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2220
2221 NotifyMotionArgs motionArgs =
2222 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2223 ADISPLAY_ID_DEFAULT, touchedPoints);
2224 mDispatcher->notifyMotion(&motionArgs);
2225 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2226
2227 // Touch Window 2
2228 int32_t actionPointerDown =
2229 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2230 touchedPoints.emplace_back(PointF{150, 150});
2231 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2232
2233 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2234 ADISPLAY_ID_DEFAULT, touchedPoints);
2235 mDispatcher->notifyMotion(&motionArgs);
2236
2237 // Consuming from window1 since it's the window that has the InputReceiver
2238 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2239
2240 // Move both windows
2241 touchedPoints = {{20, 20}, {175, 175}};
2242 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2243 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2244
2245 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2246 ADISPLAY_ID_DEFAULT, touchedPoints);
2247 mDispatcher->notifyMotion(&motionArgs);
2248
2249 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2250}
2251
2252TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2253 mWindow1->setWindowScale(0.5f, 0.5f);
2254
2255 // Touch Window 1
2256 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2257 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2258
2259 NotifyMotionArgs motionArgs =
2260 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2261 ADISPLAY_ID_DEFAULT, touchedPoints);
2262 mDispatcher->notifyMotion(&motionArgs);
2263 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2264
2265 // Touch Window 2
2266 int32_t actionPointerDown =
2267 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2268 touchedPoints.emplace_back(PointF{150, 150});
2269 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2270
2271 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2272 ADISPLAY_ID_DEFAULT, touchedPoints);
2273 mDispatcher->notifyMotion(&motionArgs);
2274
2275 // Consuming from window1 since it's the window that has the InputReceiver
2276 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2277
2278 // Move both windows
2279 touchedPoints = {{20, 20}, {175, 175}};
2280 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2281 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2282
2283 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2284 ADISPLAY_ID_DEFAULT, touchedPoints);
2285 mDispatcher->notifyMotion(&motionArgs);
2286
2287 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2288}
2289
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002290class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2291 virtual void SetUp() override {
2292 InputDispatcherTest::SetUp();
2293
2294 mApplication = new FakeApplicationHandle();
2295 mApplication->setDispatchingTimeout(20ms);
2296 mWindow =
2297 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2298 mWindow->setFrame(Rect(0, 0, 30, 30));
2299 mWindow->setDispatchingTimeout(10ms);
2300 mWindow->setFocus(true);
2301 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2302 // window.
2303 mWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
2304
2305 // Set focused application.
2306 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2307
2308 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2309 mWindow->consumeFocusEvent(true);
2310 }
2311
2312 virtual void TearDown() override {
2313 InputDispatcherTest::TearDown();
2314 mWindow.clear();
2315 }
2316
2317protected:
2318 sp<FakeApplicationHandle> mApplication;
2319 sp<FakeWindowHandle> mWindow;
2320 static constexpr PointF WINDOW_LOCATION = {20, 20};
2321
2322 void tapOnWindow() {
2323 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2324 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2325 WINDOW_LOCATION));
2326 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2327 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2328 WINDOW_LOCATION));
2329 }
2330};
2331
2332// Send an event to the app and have the app not respond right away.
2333// Make sure that ANR is raised
2334TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
2335 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2336 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2337 WINDOW_LOCATION));
2338
2339 // Also, overwhelm the socket to make sure ANR starts
2340 for (size_t i = 0; i < 100; i++) {
2341 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2342 ADISPLAY_ID_DEFAULT, {WINDOW_LOCATION.x, WINDOW_LOCATION.y + i});
2343 }
2344
2345 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2346 ASSERT_TRUE(sequenceNum);
2347 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2348 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2349 ASSERT_TRUE(mDispatcher->waitForIdle());
2350}
2351
2352// Send a key to the app and have the app not respond right away.
2353TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
2354 // Inject a key, and don't respond - expect that ANR is called.
2355 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2356 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
2357 ASSERT_TRUE(sequenceNum);
2358
2359 // Start ANR process by sending a 2nd key, which would trigger the check for whether
2360 // waitQueue is empty
2361 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 1);
2362
2363 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2364 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, mWindow->getToken());
2365 ASSERT_TRUE(mDispatcher->waitForIdle());
2366}
2367
Garfield Tane84e6f92019-08-29 17:28:41 -07002368} // namespace android::inputdispatcher