blob: ea4d885ed505e518482a10f9a87ad3bd723a68ce [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) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700129 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData;
130 ASSERT_NO_FATAL_FAILURE(anrData = getNotifyAnrData(timeout));
131 ASSERT_EQ(expectedApplication, anrData.first);
132 ASSERT_EQ(expectedToken, anrData.second);
133 }
134
135 std::pair<sp<InputApplicationHandle>, sp<IBinder>> getNotifyAnrData(
136 std::chrono::nanoseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700137 const std::chrono::time_point start = std::chrono::steady_clock::now();
138 std::unique_lock lock(mLock);
139 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
140 android::base::ScopedLockAssertion assumeLocked(mLock);
141
142 // If there is an ANR, Dispatcher won't be idle because there are still events
143 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
144 // before checking if ANR was called.
145 // Since dispatcher is not guaranteed to call notifyAnr right away, we need to provide
146 // it some time to act. 100ms seems reasonable.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700147 mNotifyAnr.wait_for(lock, timeToWait, [this]() REQUIRES(mLock) {
148 return !mAnrApplications.empty() && !mAnrWindowTokens.empty();
149 });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700150 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700151 if (mAnrApplications.empty() || mAnrWindowTokens.empty()) {
152 ADD_FAILURE() << "Did not receive ANR callback";
153 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700154 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
155 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700156 if (std::chrono::abs(timeout - waited) > 100ms) {
157 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
158 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
159 << "ms, but waited "
160 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
161 << "ms instead";
162 }
163 std::pair<sp<InputApplicationHandle>, sp<IBinder>> result =
164 std::make_pair(mAnrApplications.front(), mAnrWindowTokens.front());
165 mAnrApplications.pop();
166 mAnrWindowTokens.pop();
167 return result;
168 }
169
170 void assertNotifyAnrWasNotCalled() {
171 std::scoped_lock lock(mLock);
172 ASSERT_TRUE(mAnrApplications.empty());
173 ASSERT_TRUE(mAnrWindowTokens.empty());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700174 }
175
Garfield Tan1c7bc862020-01-28 13:24:04 -0800176 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
177 mConfig.keyRepeatTimeout = timeout;
178 mConfig.keyRepeatDelay = delay;
179 }
180
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700181 void setAnrTimeout(std::chrono::nanoseconds timeout) { mAnrTimeout = timeout; }
182
Michael Wrightd02c5b62014-02-10 15:10:22 -0800183private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700184 std::mutex mLock;
185 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
186 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
187 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
188 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800189
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700190 // ANR handling
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700191 std::queue<sp<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
192 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700193 std::condition_variable mNotifyAnr;
194 std::chrono::nanoseconds mAnrTimeout = 0ms;
195
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800196 virtual void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700197 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800198 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800199 }
200
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700201 virtual nsecs_t notifyAnr(const sp<InputApplicationHandle>& application,
202 const sp<IBinder>& windowToken, const std::string&) override {
203 std::scoped_lock lock(mLock);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700204 mAnrApplications.push(application);
205 mAnrWindowTokens.push(windowToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700206 mNotifyAnr.notify_all();
207 return mAnrTimeout.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208 }
209
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700210 virtual void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800211
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700212 virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700213
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700214 virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800215 *outConfig = mConfig;
216 }
217
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800218 virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700219 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800220 switch (inputEvent->getType()) {
221 case AINPUT_EVENT_TYPE_KEY: {
222 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800223 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800224 break;
225 }
226
227 case AINPUT_EVENT_TYPE_MOTION: {
228 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800229 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800230 break;
231 }
232 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800233 return true;
234 }
235
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700236 virtual void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800237
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700238 virtual void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800239
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700240 virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*,
241 uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800242 return 0;
243 }
244
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700245 virtual bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t,
246 KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800247 return false;
248 }
249
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800250 virtual void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
251 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700252 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800253 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
254 * essentially a passthrough for notifySwitch.
255 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800256 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800257 }
258
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700259 virtual void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800260
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700261 virtual bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800262 return false;
263 }
Jackal Guof9696682018-10-05 12:23:23 +0800264
Siarhei Vishniakoub1a16272020-05-06 16:09:19 -0700265 virtual void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700266 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700267 mOnPointerDownToken = newToken;
268 }
269
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800270 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
271 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700272 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800273 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
274 ASSERT_EQ(mFilteredEvent->getType(), type);
275
276 if (type == AINPUT_EVENT_TYPE_KEY) {
277 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
278 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
279 EXPECT_EQ(keyEvent.getAction(), action);
280 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
281 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
282 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
283 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
284 EXPECT_EQ(motionEvent.getAction(), action);
285 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
286 } else {
287 FAIL() << "Unknown type: " << type;
288 }
289
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800290 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800291 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800292};
293
Gang Wang342c9272020-01-13 13:15:04 -0500294// --- HmacKeyManagerTest ---
295
296class HmacKeyManagerTest : public testing::Test {
297protected:
298 HmacKeyManager mHmacKeyManager;
299};
300
301/**
302 * Ensure that separate calls to sign the same data are generating the same key.
303 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
304 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
305 * tests.
306 */
307TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) {
308 KeyEvent event = getTestKeyEvent();
309 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
310
311 std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent);
312 std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent);
313 ASSERT_EQ(hmac1, hmac2);
314}
315
316/**
317 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
318 */
319TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) {
320 KeyEvent event = getTestKeyEvent();
321 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
322 std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent);
323
324 verifiedEvent.deviceId += 1;
325 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
326
327 verifiedEvent.source += 1;
328 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
329
330 verifiedEvent.eventTimeNanos += 1;
331 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
332
333 verifiedEvent.displayId += 1;
334 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
335
336 verifiedEvent.action += 1;
337 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
338
339 verifiedEvent.downTimeNanos += 1;
340 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
341
342 verifiedEvent.flags += 1;
343 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
344
345 verifiedEvent.keyCode += 1;
346 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
347
348 verifiedEvent.scanCode += 1;
349 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
350
351 verifiedEvent.metaState += 1;
352 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
353
354 verifiedEvent.repeatCount += 1;
355 ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent));
356}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800357
358// --- InputDispatcherTest ---
359
360class InputDispatcherTest : public testing::Test {
361protected:
362 sp<FakeInputDispatcherPolicy> mFakePolicy;
363 sp<InputDispatcher> mDispatcher;
364
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700365 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800366 mFakePolicy = new FakeInputDispatcherPolicy();
367 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800368 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
369 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700370 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800371 }
372
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700373 virtual void TearDown() override {
374 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800375 mFakePolicy.clear();
376 mDispatcher.clear();
377 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700378
379 /**
380 * Used for debugging when writing the test
381 */
382 void dumpDispatcherState() {
383 std::string dump;
384 mDispatcher->dump(dump);
385 std::stringstream ss(dump);
386 std::string to;
387
388 while (std::getline(ss, to, '\n')) {
389 ALOGE("%s", to.c_str());
390 }
391 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800392};
393
394
395TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
396 KeyEvent event;
397
398 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800399 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
400 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600401 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
402 ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700403 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
404 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
405 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800406 << "Should reject key events with undefined action.";
407
408 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800409 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
410 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600411 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700412 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
413 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
414 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800415 << "Should reject key events with ACTION_MULTIPLE.";
416}
417
418TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
419 MotionEvent event;
420 PointerProperties pointerProperties[MAX_POINTERS + 1];
421 PointerCoords pointerCoords[MAX_POINTERS + 1];
422 for (int i = 0; i <= MAX_POINTERS; i++) {
423 pointerProperties[i].clear();
424 pointerProperties[i].id = i;
425 pointerCoords[i].clear();
426 }
427
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800428 // Some constants commonly used below
429 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
430 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
431 constexpr int32_t metaState = AMETA_NONE;
432 constexpr MotionClassification classification = MotionClassification::NONE;
433
Michael Wrightd02c5b62014-02-10 15:10:22 -0800434 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800435 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600436 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
437 1 /* yScale */, 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 undefined action.";
444
445 // Rejects pointer down 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_DOWN |
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 down 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_DOWN |
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 down index too small.";
469
470 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800471 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700472 AMOTION_EVENT_ACTION_POINTER_UP |
473 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600474 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
475 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
476 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700477 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700478 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
479 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
480 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 << "Should reject motion events with pointer up index too large.";
482
Garfield Tanfbe732e2020-01-24 11:26:14 -0800483 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700484 AMOTION_EVENT_ACTION_POINTER_UP |
485 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600486 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
487 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
488 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700489 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700490 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
491 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
492 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800493 << "Should reject motion events with pointer up index too small.";
494
495 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800496 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
497 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
498 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
499 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
500 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700501 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700502 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
503 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
504 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800505 << "Should reject motion events with 0 pointers.";
506
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*/ MAX_POINTERS + 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 more than MAX_POINTERS pointers.";
517
518 // Rejects motion events with invalid pointer ids.
519 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800520 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
521 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
522 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
523 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
524 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700525 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700526 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
527 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
528 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800529 << "Should reject motion events with pointer ids less than 0.";
530
531 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800532 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
533 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
534 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
535 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
536 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700537 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700538 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
539 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
540 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800541 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
542
543 // Rejects motion events with duplicate pointer ids.
544 pointerProperties[0].id = 1;
545 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800546 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
547 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
548 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
549 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
550 ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700551 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700552 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
553 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
554 INPUT_EVENT_INJECTION_SYNC_NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800555 << "Should reject motion events with duplicate pointer ids.";
556}
557
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800558/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
559
560TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
561 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800562 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800563 mDispatcher->notifyConfigurationChanged(&args);
564 ASSERT_TRUE(mDispatcher->waitForIdle());
565
566 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
567}
568
569TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800570 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
571 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800572 mDispatcher->notifySwitch(&args);
573
574 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
575 args.policyFlags |= POLICY_FLAG_TRUSTED;
576 mFakePolicy->assertNotifySwitchWasCalled(args);
577}
578
Arthur Hungb92218b2018-08-14 12:00:21 +0800579// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700580static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700581static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800582
583class FakeApplicationHandle : public InputApplicationHandle {
584public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700585 FakeApplicationHandle() {
586 mInfo.name = "Fake Application";
587 mInfo.token = new BBinder();
588 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
589 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800590 virtual ~FakeApplicationHandle() {}
591
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700592 virtual bool updateInfo() override {
Arthur Hungb92218b2018-08-14 12:00:21 +0800593 return true;
594 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700595
596 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
597 mInfo.dispatchingTimeout = timeout.count();
598 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800599};
600
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800601class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800602public:
chaviwd1c23182019-12-20 18:44:56 -0800603 explicit FakeInputReceiver(const sp<InputChannel>& clientChannel, const std::string name)
604 : mName(name) {
605 mConsumer = std::make_unique<InputConsumer>(clientChannel);
606 }
607
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800608 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700609 InputEvent* event;
610 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
611 if (!consumeSeq) {
612 return nullptr;
613 }
614 finishEvent(*consumeSeq);
615 return event;
616 }
617
618 /**
619 * Receive an event without acknowledging it.
620 * Return the sequence number that could later be used to send finished signal.
621 */
622 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800623 uint32_t consumeSeq;
624 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800625
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800626 std::chrono::time_point start = std::chrono::steady_clock::now();
627 status_t status = WOULD_BLOCK;
628 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800629 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800630 &event);
631 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
632 if (elapsed > 100ms) {
633 break;
634 }
635 }
636
637 if (status == WOULD_BLOCK) {
638 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700639 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800640 }
641
642 if (status != OK) {
643 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700644 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800645 }
646 if (event == nullptr) {
647 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700648 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800649 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700650 if (outEvent != nullptr) {
651 *outEvent = event;
652 }
653 return consumeSeq;
654 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800655
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700656 /**
657 * To be used together with "receiveEvent" to complete the consumption of an event.
658 */
659 void finishEvent(uint32_t consumeSeq) {
660 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
661 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800662 }
663
664 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
665 int32_t expectedFlags) {
666 InputEvent* event = consume();
667
668 ASSERT_NE(nullptr, event) << mName.c_str()
669 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800670 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700671 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800672 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800673
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800674 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800675
Tiger Huang8664f8c2018-10-11 19:14:35 +0800676 switch (expectedEventType) {
677 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800678 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
679 EXPECT_EQ(expectedAction, keyEvent.getAction());
680 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800681 break;
682 }
683 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800684 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
685 EXPECT_EQ(expectedAction, motionEvent.getAction());
686 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800687 break;
688 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100689 case AINPUT_EVENT_TYPE_FOCUS: {
690 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
691 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800692 default: {
693 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
694 }
695 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800696 }
697
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100698 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
699 InputEvent* event = consume();
700 ASSERT_NE(nullptr, event) << mName.c_str()
701 << ": consumer should have returned non-NULL event.";
702 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
703 << "Got " << inputEventTypeToString(event->getType())
704 << " event instead of FOCUS event";
705
706 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
707 << mName.c_str() << ": event displayId should always be NONE.";
708
709 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
710 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
711 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
712 }
713
chaviwd1c23182019-12-20 18:44:56 -0800714 void assertNoEvents() {
715 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700716 if (event == nullptr) {
717 return;
718 }
719 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
720 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
721 ADD_FAILURE() << "Received key event "
722 << KeyEvent::actionToString(keyEvent.getAction());
723 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
724 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
725 ADD_FAILURE() << "Received motion event "
726 << MotionEvent::actionToString(motionEvent.getAction());
727 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
728 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
729 ADD_FAILURE() << "Received focus event, hasFocus = "
730 << (focusEvent.getHasFocus() ? "true" : "false");
731 }
732 FAIL() << mName.c_str()
733 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800734 }
735
736 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
737
738protected:
739 std::unique_ptr<InputConsumer> mConsumer;
740 PreallocatedInputEventFactory mEventFactory;
741
742 std::string mName;
743};
744
745class FakeWindowHandle : public InputWindowHandle {
746public:
747 static const int32_t WIDTH = 600;
748 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800749
750 FakeWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
751 const sp<InputDispatcher>& dispatcher, const std::string name,
752 int32_t displayId, sp<IBinder> token = nullptr)
753 : mName(name) {
754 if (token == nullptr) {
755 sp<InputChannel> serverChannel, clientChannel;
756 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
757 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
758 dispatcher->registerInputChannel(serverChannel);
759 token = serverChannel->getConnectionToken();
760 }
761
762 inputApplicationHandle->updateInfo();
763 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
764
765 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700766 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800767 mInfo.name = name;
768 mInfo.layoutParamsFlags = 0;
769 mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700770 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT.count();
chaviwd1c23182019-12-20 18:44:56 -0800771 mInfo.frameLeft = 0;
772 mInfo.frameTop = 0;
773 mInfo.frameRight = WIDTH;
774 mInfo.frameBottom = HEIGHT;
775 mInfo.globalScaleFactor = 1.0;
776 mInfo.touchableRegion.clear();
777 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
778 mInfo.visible = true;
779 mInfo.canReceiveKeys = true;
780 mInfo.hasFocus = false;
781 mInfo.hasWallpaper = false;
782 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800783 mInfo.ownerPid = INJECTOR_PID;
784 mInfo.ownerUid = INJECTOR_UID;
785 mInfo.inputFeatures = 0;
786 mInfo.displayId = displayId;
787 }
788
789 virtual bool updateInfo() { return true; }
790
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100791 void setFocus(bool hasFocus) { mInfo.hasFocus = hasFocus; }
chaviwd1c23182019-12-20 18:44:56 -0800792
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700793 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
794 mInfo.dispatchingTimeout = timeout.count();
795 }
796
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700797 void setPaused(bool paused) { mInfo.paused = paused; }
798
chaviwd1c23182019-12-20 18:44:56 -0800799 void setFrame(const Rect& frame) {
800 mInfo.frameLeft = frame.left;
801 mInfo.frameTop = frame.top;
802 mInfo.frameRight = frame.right;
803 mInfo.frameBottom = frame.bottom;
804 mInfo.touchableRegion.clear();
805 mInfo.addTouchableRegion(frame);
806 }
807
808 void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; }
809
chaviwaf87b3e2019-10-01 16:59:28 -0700810 void setWindowScale(float xScale, float yScale) {
811 mInfo.windowXScale = xScale;
812 mInfo.windowYScale = yScale;
813 }
814
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800815 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
816 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
817 expectedFlags);
818 }
819
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700820 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
821 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
822 }
823
Svet Ganov5d3bc372020-01-26 23:11:07 -0800824 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
825 int32_t expectedFlags = 0) {
826 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
827 expectedFlags);
828 }
829
830 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
831 int32_t expectedFlags = 0) {
832 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
833 expectedFlags);
834 }
835
836 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
837 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800838 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
839 expectedFlags);
840 }
841
Svet Ganov5d3bc372020-01-26 23:11:07 -0800842 void consumeMotionPointerDown(int32_t pointerIdx,
843 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
844 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
845 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
846 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
847 }
848
849 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
850 int32_t expectedFlags = 0) {
851 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
852 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
853 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
854 }
855
856 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
857 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000858 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
859 expectedFlags);
860 }
861
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100862 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
863 ASSERT_NE(mInputReceiver, nullptr)
864 << "Cannot consume events from a window with no receiver";
865 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
866 }
867
chaviwd1c23182019-12-20 18:44:56 -0800868 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
869 int32_t expectedFlags) {
870 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
871 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
872 expectedFlags);
873 }
874
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700875 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700876 if (mInputReceiver == nullptr) {
877 ADD_FAILURE() << "Invalid receive event on window with no receiver";
878 return std::nullopt;
879 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700880 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881 }
882
883 void finishEvent(uint32_t sequenceNum) {
884 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
885 mInputReceiver->finishEvent(sequenceNum);
886 }
887
chaviwaf87b3e2019-10-01 16:59:28 -0700888 InputEvent* consume() {
889 if (mInputReceiver == nullptr) {
890 return nullptr;
891 }
892 return mInputReceiver->consume();
893 }
894
Arthur Hungb92218b2018-08-14 12:00:21 +0800895 void assertNoEvents() {
chaviwd1c23182019-12-20 18:44:56 -0800896 ASSERT_NE(mInputReceiver, nullptr)
897 << "Call 'assertNoEvents' on a window with an InputReceiver";
898 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800899 }
900
chaviwaf87b3e2019-10-01 16:59:28 -0700901 sp<IBinder> getToken() { return mInfo.token; }
902
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100903 const std::string& getName() { return mName; }
904
chaviwd1c23182019-12-20 18:44:56 -0800905private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100906 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800907 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700908 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800909};
910
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700911std::atomic<int32_t> FakeWindowHandle::sId{1};
912
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700913static int32_t injectKey(const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700914 int32_t displayId = ADISPLAY_ID_NONE,
915 int32_t syncMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
916 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800917 KeyEvent event;
918 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
919
920 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800921 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700922 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
923 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800924
925 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700926 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
927 injectionTimeout,
928 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800929}
930
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700931static int32_t injectKeyDown(const sp<InputDispatcher>& dispatcher,
932 int32_t displayId = ADISPLAY_ID_NONE) {
933 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
934}
935
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700936static int32_t injectKeyUp(const sp<InputDispatcher>& dispatcher,
937 int32_t displayId = ADISPLAY_ID_NONE) {
938 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
939}
940
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700941static int32_t injectMotionEvent(
942 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
943 const PointF& position,
944 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700945 AMOTION_EVENT_INVALID_CURSOR_POSITION},
946 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
947 int32_t injectionMode = INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
948 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800949 MotionEvent event;
950 PointerProperties pointerProperties[1];
951 PointerCoords pointerCoords[1];
952
953 pointerProperties[0].clear();
954 pointerProperties[0].id = 0;
955 pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
956
957 pointerCoords[0].clear();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700958 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, position.x);
959 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, position.y);
Arthur Hungb92218b2018-08-14 12:00:21 +0800960
Arthur Hungb92218b2018-08-14 12:00:21 +0800961 // Define a valid motion down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800962 event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
963 /* actionButton */ 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600964 /* flags */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700965 /* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600966 /* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700967 /* xPrecision */ 0, /* yPrecision */ 0, cursorPosition.x, cursorPosition.y,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700968 eventTime, eventTime,
Garfield Tan00f511d2019-06-12 16:55:40 -0700969 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Arthur Hungb92218b2018-08-14 12:00:21 +0800970
971 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700972 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
973 injectionTimeout,
974 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800975}
976
Garfield Tan00f511d2019-06-12 16:55:40 -0700977static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700978 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700979 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700980}
981
Michael Wright3a240c42019-12-10 20:53:41 +0000982static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700983 int32_t displayId, const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700984 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000985}
986
Jackal Guof9696682018-10-05 12:23:23 +0800987static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
988 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
989 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800990 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
991 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
992 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800993
994 return args;
995}
996
chaviwd1c23182019-12-20 18:44:56 -0800997static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
998 const std::vector<PointF>& points) {
999 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001000 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1001 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1002 }
1003
chaviwd1c23182019-12-20 18:44:56 -08001004 PointerProperties pointerProperties[pointerCount];
1005 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001006
chaviwd1c23182019-12-20 18:44:56 -08001007 for (size_t i = 0; i < pointerCount; i++) {
1008 pointerProperties[i].clear();
1009 pointerProperties[i].id = i;
1010 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001011
chaviwd1c23182019-12-20 18:44:56 -08001012 pointerCoords[i].clear();
1013 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1014 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1015 }
Jackal Guof9696682018-10-05 12:23:23 +08001016
1017 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1018 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001019 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001020 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1021 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001022 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1023 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001024 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1025 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001026
1027 return args;
1028}
1029
chaviwd1c23182019-12-20 18:44:56 -08001030static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1031 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1032}
1033
Arthur Hungb92218b2018-08-14 12:00:21 +08001034TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
1035 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001036 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
1037 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001038
Arthur Hung72d8dc32020-03-28 00:48:39 +00001039 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001040 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1041 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001042 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1043
1044 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001045 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001046}
1047
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001048/**
1049 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1050 * To ensure that window receives only events that were directly inside of it, add
1051 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1052 * when finding touched windows.
1053 * This test serves as a sanity check for the next test, where setInputWindows is
1054 * called twice.
1055 */
1056TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
1057 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1058 sp<FakeWindowHandle> window =
1059 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1060 window->setFrame(Rect(0, 0, 100, 100));
1061 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1062
1063 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1064 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1065 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1066 {50, 50}))
1067 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1068
1069 // Window should receive motion event.
1070 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1071}
1072
1073/**
1074 * Calling setInputWindows twice, with the same info, should not cause any issues.
1075 * To ensure that window receives only events that were directly inside of it, add
1076 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1077 * when finding touched windows.
1078 */
1079TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
1080 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1081 sp<FakeWindowHandle> window =
1082 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1083 window->setFrame(Rect(0, 0, 100, 100));
1084 window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1085
1086 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1088 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1089 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1090 {50, 50}))
1091 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1092
1093 // Window should receive motion event.
1094 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1095}
1096
Arthur Hungb92218b2018-08-14 12:00:21 +08001097// The foreground window should receive the first touch down event.
1098TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
1099 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001100 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1101 ADISPLAY_ID_DEFAULT);
1102 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1103 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001104
Arthur Hung72d8dc32020-03-28 00:48:39 +00001105 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001106 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1107 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001108 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1109
1110 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001111 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001112 windowSecond->assertNoEvents();
1113}
1114
1115TEST_F(InputDispatcherTest, SetInputWindow_FocusedWindow) {
1116 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001117 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1118 ADISPLAY_ID_DEFAULT);
1119 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1120 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001121
Arthur Hung7ab76b12019-01-09 19:17:20 +08001122 // Set focused application.
Tiger Huang721e26f2018-07-24 22:26:19 +08001123 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hungb92218b2018-08-14 12:00:21 +08001124
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001125 // Display should have only one focused window
1126 windowSecond->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001127 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001128
1129 windowSecond->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001130 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1131 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1132
1133 // Focused window should receive event.
1134 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001135 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001136}
1137
Arthur Hung7ab76b12019-01-09 19:17:20 +08001138TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
1139 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1140 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1141 ADISPLAY_ID_DEFAULT);
1142 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1143 ADISPLAY_ID_DEFAULT);
1144
1145 // Set focused application.
1146 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1147
1148 // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001149 windowTop->setFocus(true);
1150 windowSecond->setFocus(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001151
Arthur Hung72d8dc32020-03-28 00:48:39 +00001152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001153 windowTop->consumeFocusEvent(true);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001154 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1155 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1156
1157 // Top focused window should receive event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001158 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung7ab76b12019-01-09 19:17:20 +08001159 windowSecond->assertNoEvents();
1160}
1161
Arthur Hung3b413f22018-10-26 18:05:34 +08001162TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
1163 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1164
1165 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1166 ADISPLAY_ID_DEFAULT);
1167 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1168 ADISPLAY_ID_DEFAULT);
1169
Arthur Hung832bc4a2019-01-28 11:43:17 +08001170 // Set focused application.
1171 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Arthur Hung3b413f22018-10-26 18:05:34 +08001172
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001173 windowTop->setFocus(true);
1174 windowSecond->setFocus(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001175 // Release channel for window is no longer valid.
1176 windowTop->releaseChannel();
Arthur Hung72d8dc32020-03-28 00:48:39 +00001177 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001178 windowSecond->consumeFocusEvent(true);
Arthur Hung3b413f22018-10-26 18:05:34 +08001179
Arthur Hung832bc4a2019-01-28 11:43:17 +08001180 // Test inject a key down, should dispatch to a valid window.
1181 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1182 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Arthur Hung3b413f22018-10-26 18:05:34 +08001183
1184 // Top window is invalid, so it should not receive any input event.
1185 windowTop->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001186 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung3b413f22018-10-26 18:05:34 +08001187}
1188
Garfield Tan00f511d2019-06-12 16:55:40 -07001189TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
1190 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1191
1192 sp<FakeWindowHandle> windowLeft =
1193 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1194 windowLeft->setFrame(Rect(0, 0, 600, 800));
1195 windowLeft->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1196 sp<FakeWindowHandle> windowRight =
1197 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1198 windowRight->setFrame(Rect(600, 0, 1200, 800));
1199 windowRight->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
1200
1201 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1202
Arthur Hung72d8dc32020-03-28 00:48:39 +00001203 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001204
1205 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1206 // left window. This event should be dispatched to the left window.
1207 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1208 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001209 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001210 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001211 windowRight->assertNoEvents();
1212}
1213
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001214TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
1215 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1216 sp<FakeWindowHandle> window =
1217 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001218 window->setFocus(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001219
Arthur Hung72d8dc32020-03-28 00:48:39 +00001220 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001221 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001222
1223 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1224 mDispatcher->notifyKey(&keyArgs);
1225
1226 // Window should receive key down event.
1227 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1228
1229 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1230 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001231 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001232 mDispatcher->notifyDeviceReset(&args);
1233 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1234 AKEY_EVENT_FLAG_CANCELED);
1235}
1236
1237TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
1238 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1239 sp<FakeWindowHandle> window =
1240 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1241
Arthur Hung72d8dc32020-03-28 00:48:39 +00001242 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001243
1244 NotifyMotionArgs motionArgs =
1245 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1246 ADISPLAY_ID_DEFAULT);
1247 mDispatcher->notifyMotion(&motionArgs);
1248
1249 // Window should receive motion down event.
1250 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1251
1252 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1253 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001254 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001255 mDispatcher->notifyDeviceReset(&args);
1256 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1257 0 /*expectedFlags*/);
1258}
1259
Svet Ganov5d3bc372020-01-26 23:11:07 -08001260TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
1261 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1262
1263 // Create a couple of windows
1264 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1265 "First Window", ADISPLAY_ID_DEFAULT);
1266 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1267 "Second Window", ADISPLAY_ID_DEFAULT);
1268
1269 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001270 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001271
1272 // Send down to the first window
1273 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1274 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1275 mDispatcher->notifyMotion(&downMotionArgs);
1276 // Only the first window should get the down event
1277 firstWindow->consumeMotionDown();
1278 secondWindow->assertNoEvents();
1279
1280 // Transfer touch focus to the second window
1281 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1282 // The first window gets cancel and the second gets down
1283 firstWindow->consumeMotionCancel();
1284 secondWindow->consumeMotionDown();
1285
1286 // Send up event to the second window
1287 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1288 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1289 mDispatcher->notifyMotion(&upMotionArgs);
1290 // The first window gets no events and the second gets up
1291 firstWindow->assertNoEvents();
1292 secondWindow->consumeMotionUp();
1293}
1294
1295TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
1296 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1297
1298 PointF touchPoint = {10, 10};
1299
1300 // Create a couple of windows
1301 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1302 "First Window", ADISPLAY_ID_DEFAULT);
1303 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1304 "Second Window", ADISPLAY_ID_DEFAULT);
1305
1306 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001307 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001308
1309 // Send down to the first window
1310 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1311 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1312 mDispatcher->notifyMotion(&downMotionArgs);
1313 // Only the first window should get the down event
1314 firstWindow->consumeMotionDown();
1315 secondWindow->assertNoEvents();
1316
1317 // Send pointer down to the first window
1318 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1319 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1320 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1321 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1322 // Only the first window should get the pointer down event
1323 firstWindow->consumeMotionPointerDown(1);
1324 secondWindow->assertNoEvents();
1325
1326 // Transfer touch focus to the second window
1327 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1328 // The first window gets cancel and the second gets down and pointer down
1329 firstWindow->consumeMotionCancel();
1330 secondWindow->consumeMotionDown();
1331 secondWindow->consumeMotionPointerDown(1);
1332
1333 // Send pointer up to the second window
1334 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1335 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1336 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1337 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1338 // The first window gets nothing and the second gets pointer up
1339 firstWindow->assertNoEvents();
1340 secondWindow->consumeMotionPointerUp(1);
1341
1342 // Send up event to the second window
1343 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1344 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1345 mDispatcher->notifyMotion(&upMotionArgs);
1346 // The first window gets nothing and the second gets up
1347 firstWindow->assertNoEvents();
1348 secondWindow->consumeMotionUp();
1349}
1350
1351TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
1352 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1353
1354 // Create a non touch modal window that supports split touch
1355 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1356 "First Window", ADISPLAY_ID_DEFAULT);
1357 firstWindow->setFrame(Rect(0, 0, 600, 400));
1358 firstWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1359 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1360
1361 // Create a non touch modal window that supports split touch
1362 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1363 "Second Window", ADISPLAY_ID_DEFAULT);
1364 secondWindow->setFrame(Rect(0, 400, 600, 800));
1365 secondWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL
1366 | InputWindowInfo::FLAG_SPLIT_TOUCH);
1367
1368 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001369 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001370
1371 PointF pointInFirst = {300, 200};
1372 PointF pointInSecond = {300, 600};
1373
1374 // Send down to the first window
1375 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1376 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1377 mDispatcher->notifyMotion(&firstDownMotionArgs);
1378 // Only the first window should get the down event
1379 firstWindow->consumeMotionDown();
1380 secondWindow->assertNoEvents();
1381
1382 // Send down to the second window
1383 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1384 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1385 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1386 mDispatcher->notifyMotion(&secondDownMotionArgs);
1387 // The first window gets a move and the second a down
1388 firstWindow->consumeMotionMove();
1389 secondWindow->consumeMotionDown();
1390
1391 // Transfer touch focus to the second window
1392 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1393 // The first window gets cancel and the new gets pointer down (it already saw down)
1394 firstWindow->consumeMotionCancel();
1395 secondWindow->consumeMotionPointerDown(1);
1396
1397 // Send pointer up to the second window
1398 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1399 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1400 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1401 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1402 // The first window gets nothing and the second gets pointer up
1403 firstWindow->assertNoEvents();
1404 secondWindow->consumeMotionPointerUp(1);
1405
1406 // Send up event to the second window
1407 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1408 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1409 mDispatcher->notifyMotion(&upMotionArgs);
1410 // The first window gets nothing and the second gets up
1411 firstWindow->assertNoEvents();
1412 secondWindow->consumeMotionUp();
1413}
1414
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001415TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
1416 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1417 sp<FakeWindowHandle> window =
1418 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1419
1420 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001421 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001422
1423 window->consumeFocusEvent(true);
1424
1425 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1426 mDispatcher->notifyKey(&keyArgs);
1427
1428 // Window should receive key down event.
1429 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1430}
1431
1432TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
1433 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1434 sp<FakeWindowHandle> window =
1435 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1436
Arthur Hung72d8dc32020-03-28 00:48:39 +00001437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001438
1439 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1440 mDispatcher->notifyKey(&keyArgs);
1441 mDispatcher->waitForIdle();
1442
1443 window->assertNoEvents();
1444}
1445
1446// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1447TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
1448 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1449 sp<FakeWindowHandle> window =
1450 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1451
Arthur Hung72d8dc32020-03-28 00:48:39 +00001452 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001453
1454 // Send key
1455 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1456 mDispatcher->notifyKey(&keyArgs);
1457 // Send motion
1458 NotifyMotionArgs motionArgs =
1459 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1460 ADISPLAY_ID_DEFAULT);
1461 mDispatcher->notifyMotion(&motionArgs);
1462
1463 // Window should receive only the motion event
1464 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1465 window->assertNoEvents(); // Key event or focus event will not be received
1466}
1467
chaviwd1c23182019-12-20 18:44:56 -08001468class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001469public:
1470 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001471 int32_t displayId, bool isGestureMonitor = false) {
1472 sp<InputChannel> serverChannel, clientChannel;
1473 InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
1474 mInputReceiver = std::make_unique<FakeInputReceiver>(clientChannel, name);
1475 dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor);
Michael Wright3a240c42019-12-10 20:53:41 +00001476 }
1477
chaviwd1c23182019-12-20 18:44:56 -08001478 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1479
1480 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1481 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1482 expectedDisplayId, expectedFlags);
1483 }
1484
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001485 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1486
1487 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1488
chaviwd1c23182019-12-20 18:44:56 -08001489 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1490 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1491 expectedDisplayId, expectedFlags);
1492 }
1493
1494 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1495 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1496 expectedDisplayId, expectedFlags);
1497 }
1498
1499 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1500
1501private:
1502 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001503};
1504
1505// Tests for gesture monitors
1506TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
1507 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1508 sp<FakeWindowHandle> window =
1509 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001510 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001511
chaviwd1c23182019-12-20 18:44:56 -08001512 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1513 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001514
1515 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1516 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1517 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1518 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001519 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001520}
1521
1522TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
1523 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1524 sp<FakeWindowHandle> window =
1525 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1526
1527 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001528 window->setFocus(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001529
Arthur Hung72d8dc32020-03-28 00:48:39 +00001530 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001531 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001532
chaviwd1c23182019-12-20 18:44:56 -08001533 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1534 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001535
1536 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1537 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1538 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001539 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001540}
1541
1542TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
1543 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1544 sp<FakeWindowHandle> window =
1545 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001546 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001547
chaviwd1c23182019-12-20 18:44:56 -08001548 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1549 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001550
1551 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1552 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1553 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1554 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001555 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001556
1557 window->releaseChannel();
1558
chaviwd1c23182019-12-20 18:44:56 -08001559 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001560
1561 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1562 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1563 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001564 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001565}
1566
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001567TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1568 FakeMonitorReceiver monitor =
1569 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1570 true /*isGestureMonitor*/);
1571
1572 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
1573 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1574 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1575 ASSERT_TRUE(consumeSeq);
1576
1577 mFakePolicy->assertNotifyAnrWasCalled(DISPATCHING_TIMEOUT, nullptr, monitor.getToken());
1578 monitor.finishEvent(*consumeSeq);
1579 ASSERT_TRUE(mDispatcher->waitForIdle());
1580}
1581
chaviw81e2bb92019-12-18 15:03:51 -08001582TEST_F(InputDispatcherTest, TestMoveEvent) {
1583 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1584 sp<FakeWindowHandle> window =
1585 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1586
Arthur Hung72d8dc32020-03-28 00:48:39 +00001587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001588
1589 NotifyMotionArgs motionArgs =
1590 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1591 ADISPLAY_ID_DEFAULT);
1592
1593 mDispatcher->notifyMotion(&motionArgs);
1594 // Window should receive motion down event.
1595 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1596
1597 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001598 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001599 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1600 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1601 motionArgs.pointerCoords[0].getX() - 10);
1602
1603 mDispatcher->notifyMotion(&motionArgs);
1604 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1605 0 /*expectedFlags*/);
1606}
1607
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001608/**
1609 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1610 * the device default right away. In the test scenario, we check both the default value,
1611 * and the action of enabling / disabling.
1612 */
1613TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
1614 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1615 sp<FakeWindowHandle> window =
1616 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1617
1618 // Set focused application.
1619 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1620 window->setFocus(true);
1621
1622 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001623 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001624 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1625
1626 SCOPED_TRACE("Remove the window to trigger focus loss");
1627 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001628 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001629 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1630
1631 SCOPED_TRACE("Disable touch mode");
1632 mDispatcher->setInTouchMode(false);
1633 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001635 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1636
1637 SCOPED_TRACE("Remove the window to trigger focus loss");
1638 window->setFocus(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001639 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001640 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1641
1642 SCOPED_TRACE("Enable touch mode again");
1643 mDispatcher->setInTouchMode(true);
1644 window->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001645 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001646 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1647
1648 window->assertNoEvents();
1649}
1650
Gang Wange9087892020-01-07 12:17:14 -05001651TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
1652 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1653 sp<FakeWindowHandle> window =
1654 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1655
1656 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1657 window->setFocus(true);
1658
Arthur Hung72d8dc32020-03-28 00:48:39 +00001659 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Gang Wange9087892020-01-07 12:17:14 -05001660 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1661
1662 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1663 mDispatcher->notifyKey(&keyArgs);
1664
1665 InputEvent* event = window->consume();
1666 ASSERT_NE(event, nullptr);
1667
1668 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1669 ASSERT_NE(verified, nullptr);
1670 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1671
1672 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1673 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1674 ASSERT_EQ(keyArgs.source, verified->source);
1675 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1676
1677 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1678
1679 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1680 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001681 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1682 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1683 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1684 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1685 ASSERT_EQ(0, verifiedKey.repeatCount);
1686}
1687
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001688TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
1689 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
1690 sp<FakeWindowHandle> window =
1691 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1692
1693 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1694
Arthur Hung72d8dc32020-03-28 00:48:39 +00001695 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001696
1697 NotifyMotionArgs motionArgs =
1698 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1699 ADISPLAY_ID_DEFAULT);
1700 mDispatcher->notifyMotion(&motionArgs);
1701
1702 InputEvent* event = window->consume();
1703 ASSERT_NE(event, nullptr);
1704
1705 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1706 ASSERT_NE(verified, nullptr);
1707 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
1708
1709 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
1710 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
1711 EXPECT_EQ(motionArgs.source, verified->source);
1712 EXPECT_EQ(motionArgs.displayId, verified->displayId);
1713
1714 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
1715
1716 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
1717 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
1718 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
1719 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
1720 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
1721 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
1722 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
1723}
1724
Garfield Tan1c7bc862020-01-28 13:24:04 -08001725class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
1726protected:
1727 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
1728 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
1729
1730 sp<FakeApplicationHandle> mApp;
1731 sp<FakeWindowHandle> mWindow;
1732
1733 virtual void SetUp() override {
1734 mFakePolicy = new FakeInputDispatcherPolicy();
1735 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
1736 mDispatcher = new InputDispatcher(mFakePolicy);
1737 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
1738 ASSERT_EQ(OK, mDispatcher->start());
1739
1740 setUpWindow();
1741 }
1742
1743 void setUpWindow() {
1744 mApp = new FakeApplicationHandle();
1745 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1746
1747 mWindow->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001748 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Garfield Tan1c7bc862020-01-28 13:24:04 -08001749
1750 mWindow->consumeFocusEvent(true);
1751 }
1752
1753 void sendAndConsumeKeyDown() {
1754 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1755 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
1756 mDispatcher->notifyKey(&keyArgs);
1757
1758 // Window should receive key down event.
1759 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1760 }
1761
1762 void expectKeyRepeatOnce(int32_t repeatCount) {
1763 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
1764 InputEvent* repeatEvent = mWindow->consume();
1765 ASSERT_NE(nullptr, repeatEvent);
1766
1767 uint32_t eventType = repeatEvent->getType();
1768 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
1769
1770 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
1771 uint32_t eventAction = repeatKeyEvent->getAction();
1772 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
1773 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
1774 }
1775
1776 void sendAndConsumeKeyUp() {
1777 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
1778 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
1779 mDispatcher->notifyKey(&keyArgs);
1780
1781 // Window should receive key down event.
1782 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1783 0 /*expectedFlags*/);
1784 }
1785};
1786
1787TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
1788 sendAndConsumeKeyDown();
1789 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1790 expectKeyRepeatOnce(repeatCount);
1791 }
1792}
1793
1794TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
1795 sendAndConsumeKeyDown();
1796 expectKeyRepeatOnce(1 /*repeatCount*/);
1797 sendAndConsumeKeyUp();
1798 mWindow->assertNoEvents();
1799}
1800
1801TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
1802 sendAndConsumeKeyDown();
1803 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1804 InputEvent* repeatEvent = mWindow->consume();
1805 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1806 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
1807 IdGenerator::getSource(repeatEvent->getId()));
1808 }
1809}
1810
1811TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
1812 sendAndConsumeKeyDown();
1813
1814 std::unordered_set<int32_t> idSet;
1815 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
1816 InputEvent* repeatEvent = mWindow->consume();
1817 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
1818 int32_t id = repeatEvent->getId();
1819 EXPECT_EQ(idSet.end(), idSet.find(id));
1820 idSet.insert(id);
1821 }
1822}
1823
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001824/* Test InputDispatcher for MultiDisplay */
1825class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
1826public:
1827 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001828 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001829 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08001830
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001831 application1 = new FakeApplicationHandle();
1832 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
1833 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001834
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001835 // Set focus window for primary display, but focused display would be second one.
1836 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001837 windowInPrimary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001838 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001839 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08001840
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001841 application2 = new FakeApplicationHandle();
1842 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
1843 SECOND_DISPLAY_ID);
1844 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001845 // Set focus display to second one.
1846 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
1847 // Set focus window for second display.
1848 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001849 windowInSecondary->setFocus(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001850 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001851 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001852 }
1853
Prabir Pradhan3608aad2019-10-02 17:08:26 -07001854 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001855 InputDispatcherTest::TearDown();
1856
1857 application1.clear();
1858 windowInPrimary.clear();
1859 application2.clear();
1860 windowInSecondary.clear();
1861 }
1862
1863protected:
1864 sp<FakeApplicationHandle> application1;
1865 sp<FakeWindowHandle> windowInPrimary;
1866 sp<FakeApplicationHandle> application2;
1867 sp<FakeWindowHandle> windowInSecondary;
1868};
1869
1870TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
1871 // Test touch down on primary display.
1872 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1873 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungb92218b2018-08-14 12:00:21 +08001874 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001875 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001876 windowInSecondary->assertNoEvents();
1877
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001878 // Test touch down on second display.
1879 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1880 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungb92218b2018-08-14 12:00:21 +08001881 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1882 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001883 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08001884}
1885
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001886TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08001887 // Test inject a key down with display id specified.
1888 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1889 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001890 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08001891 windowInSecondary->assertNoEvents();
1892
1893 // Test inject a key down without display id specified.
Arthur Hungb92218b2018-08-14 12:00:21 +08001894 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1895 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1896 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001897 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08001898
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08001899 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00001900 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08001901
1902 // Expect old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001903 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
1904 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08001905
1906 // Test inject a key down, should timeout because of no target window.
1907 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
1908 << "Inject key event should return INPUT_EVENT_INJECTION_TIMED_OUT";
1909 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001910 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08001911 windowInSecondary->assertNoEvents();
1912}
1913
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001914// Test per-display input monitors for motion event.
1915TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08001916 FakeMonitorReceiver monitorInPrimary =
1917 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1918 FakeMonitorReceiver monitorInSecondary =
1919 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001920
1921 // Test touch down on primary display.
1922 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1923 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1924 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001925 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001926 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001927 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001928 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001929
1930 // Test touch down on second display.
1931 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1932 AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
1933 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1934 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001935 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001936 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08001937 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001938
1939 // Test inject a non-pointer motion event.
1940 // If specific a display, it will dispatch to the focused window of particular display,
1941 // or it will dispatch to the focused window of focused display.
1942 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
1943 AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
1944 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1945 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001946 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001947 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001948 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001949}
1950
1951// Test per-display input monitors for key event.
1952TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
1953 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08001954 FakeMonitorReceiver monitorInPrimary =
1955 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
1956 FakeMonitorReceiver monitorInSecondary =
1957 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001958
1959 // Test inject a key down.
1960 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
1961 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
1962 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08001963 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001964 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08001965 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001966}
1967
Jackal Guof9696682018-10-05 12:23:23 +08001968class InputFilterTest : public InputDispatcherTest {
1969protected:
1970 static constexpr int32_t SECOND_DISPLAY_ID = 1;
1971
1972 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
1973 NotifyMotionArgs motionArgs;
1974
1975 motionArgs = generateMotionArgs(
1976 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1977 mDispatcher->notifyMotion(&motionArgs);
1978 motionArgs = generateMotionArgs(
1979 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
1980 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001981 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001982 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001983 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08001984 } else {
1985 mFakePolicy->assertFilterInputEventWasNotCalled();
1986 }
1987 }
1988
1989 void testNotifyKey(bool expectToBeFiltered) {
1990 NotifyKeyArgs keyArgs;
1991
1992 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1993 mDispatcher->notifyKey(&keyArgs);
1994 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
1995 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001996 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08001997
1998 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08001999 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002000 } else {
2001 mFakePolicy->assertFilterInputEventWasNotCalled();
2002 }
2003 }
2004};
2005
2006// Test InputFilter for MotionEvent
2007TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2008 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2009 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2010 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2011
2012 // Enable InputFilter
2013 mDispatcher->setInputFilterEnabled(true);
2014 // Test touch on both primary and second display, and check if both events are filtered.
2015 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2016 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2017
2018 // Disable InputFilter
2019 mDispatcher->setInputFilterEnabled(false);
2020 // Test touch on both primary and second display, and check if both events aren't filtered.
2021 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2022 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2023}
2024
2025// Test InputFilter for KeyEvent
2026TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2027 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2028 testNotifyKey(/*expectToBeFiltered*/ false);
2029
2030 // Enable InputFilter
2031 mDispatcher->setInputFilterEnabled(true);
2032 // Send a key event, and check if it is filtered.
2033 testNotifyKey(/*expectToBeFiltered*/ true);
2034
2035 // Disable InputFilter
2036 mDispatcher->setInputFilterEnabled(false);
2037 // Send a key event, and check if it isn't filtered.
2038 testNotifyKey(/*expectToBeFiltered*/ false);
2039}
2040
chaviwfd6d3512019-03-25 13:23:49 -07002041class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002042 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002043 InputDispatcherTest::SetUp();
2044
2045 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2046 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
2047 ADISPLAY_ID_DEFAULT);
2048 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2049 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2050 // window.
2051 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
2052
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002053 mFocusedWindow =
2054 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2055 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
2056 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002057
2058 // Set focused application.
2059 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002060 mFocusedWindow->setFocus(true);
chaviwfd6d3512019-03-25 13:23:49 -07002061
2062 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002063 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002064 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002065 }
2066
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002067 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002068 InputDispatcherTest::TearDown();
2069
2070 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002071 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002072 }
2073
2074protected:
2075 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002076 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002077 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002078};
2079
2080// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2081// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2082// the onPointerDownOutsideFocus callback.
2083TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002084 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2085 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2086 {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002087 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002088 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002089
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002090 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002091 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2092}
2093
2094// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2095// DOWN on the window that doesn't have focus. Ensure no window received the
2096// onPointerDownOutsideFocus callback.
2097TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002098 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2099 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
chaviwfd6d3512019-03-25 13:23:49 -07002100 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002101 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002102
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002103 ASSERT_TRUE(mDispatcher->waitForIdle());
2104 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002105}
2106
2107// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2108// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2109TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
2110 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2111 << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002112 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002113
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002114 ASSERT_TRUE(mDispatcher->waitForIdle());
2115 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002116}
2117
2118// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2119// DOWN on the window that already has focus. Ensure no window received the
2120// onPointerDownOutsideFocus callback.
2121TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2122 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002123 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2124 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002125 FOCUSED_WINDOW_TOUCH_POINT))
chaviwfd6d3512019-03-25 13:23:49 -07002126 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002127 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002128
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002129 ASSERT_TRUE(mDispatcher->waitForIdle());
2130 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002131}
2132
chaviwaf87b3e2019-10-01 16:59:28 -07002133// These tests ensures we can send touch events to a single client when there are multiple input
2134// windows that point to the same client token.
2135class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2136 virtual void SetUp() override {
2137 InputDispatcherTest::SetUp();
2138
2139 sp<FakeApplicationHandle> application = new FakeApplicationHandle();
2140 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2141 ADISPLAY_ID_DEFAULT);
2142 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2143 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
2144 mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2145 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002146 mWindow1->setFrame(Rect(0, 0, 100, 100));
2147
2148 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2149 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
2150 mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2151 InputWindowInfo::FLAG_SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002152 mWindow2->setFrame(Rect(100, 100, 200, 200));
2153
Arthur Hung72d8dc32020-03-28 00:48:39 +00002154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002155 }
2156
2157protected:
2158 sp<FakeWindowHandle> mWindow1;
2159 sp<FakeWindowHandle> mWindow2;
2160
2161 // Helper function to convert the point from screen coordinates into the window's space
2162 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
2163 float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft);
2164 float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop);
2165 return {x, y};
2166 }
2167
2168 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2169 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002170 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002171 InputEvent* event = window->consume();
2172
2173 ASSERT_NE(nullptr, event) << name.c_str()
2174 << ": consumer should have returned non-NULL event.";
2175
2176 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2177 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2178 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2179
2180 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2181 EXPECT_EQ(expectedAction, motionEvent.getAction());
2182
2183 for (size_t i = 0; i < points.size(); i++) {
2184 float expectedX = points[i].x;
2185 float expectedY = points[i].y;
2186
2187 EXPECT_EQ(expectedX, motionEvent.getX(i))
2188 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2189 << ", got " << motionEvent.getX(i);
2190 EXPECT_EQ(expectedY, motionEvent.getY(i))
2191 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2192 << ", got " << motionEvent.getY(i);
2193 }
2194 }
2195};
2196
2197TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2198 // Touch Window 1
2199 PointF touchedPoint = {10, 10};
2200 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2201
2202 NotifyMotionArgs motionArgs =
2203 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2204 ADISPLAY_ID_DEFAULT, {touchedPoint});
2205 mDispatcher->notifyMotion(&motionArgs);
2206 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2207
2208 // Release touch on Window 1
2209 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2210 ADISPLAY_ID_DEFAULT, {touchedPoint});
2211 mDispatcher->notifyMotion(&motionArgs);
2212 // consume the UP event
2213 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2214
2215 // Touch Window 2
2216 touchedPoint = {150, 150};
2217 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2218
2219 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2220 ADISPLAY_ID_DEFAULT, {touchedPoint});
2221 mDispatcher->notifyMotion(&motionArgs);
2222
2223 // Consuming from window1 since it's the window that has the InputReceiver
2224 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2225}
2226
2227TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) {
2228 mWindow2->setWindowScale(0.5f, 0.5f);
2229
2230 // Touch Window 1
2231 PointF touchedPoint = {10, 10};
2232 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
2233
2234 NotifyMotionArgs motionArgs =
2235 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2236 ADISPLAY_ID_DEFAULT, {touchedPoint});
2237 mDispatcher->notifyMotion(&motionArgs);
2238 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2239
2240 // Release touch on Window 1
2241 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2242 ADISPLAY_ID_DEFAULT, {touchedPoint});
2243 mDispatcher->notifyMotion(&motionArgs);
2244 // consume the UP event
2245 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint});
2246
2247 // Touch Window 2
2248 touchedPoint = {150, 150};
2249 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2250
2251 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2252 ADISPLAY_ID_DEFAULT, {touchedPoint});
2253 mDispatcher->notifyMotion(&motionArgs);
2254
2255 // Consuming from window1 since it's the window that has the InputReceiver
2256 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint});
2257}
2258
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002259TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentScale) {
2260 mWindow2->setWindowScale(0.5f, 0.5f);
2261
2262 // Touch Window 1
2263 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2264 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2265
2266 NotifyMotionArgs motionArgs =
2267 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2268 ADISPLAY_ID_DEFAULT, touchedPoints);
2269 mDispatcher->notifyMotion(&motionArgs);
2270 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2271
2272 // Touch Window 2
2273 int32_t actionPointerDown =
2274 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2275 touchedPoints.emplace_back(PointF{150, 150});
2276 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2277
2278 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2279 ADISPLAY_ID_DEFAULT, touchedPoints);
2280 mDispatcher->notifyMotion(&motionArgs);
2281
2282 // Consuming from window1 since it's the window that has the InputReceiver
2283 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2284}
2285
2286TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentScale) {
2287 mWindow2->setWindowScale(0.5f, 0.5f);
2288
2289 // Touch Window 1
2290 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2291 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2292
2293 NotifyMotionArgs motionArgs =
2294 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2295 ADISPLAY_ID_DEFAULT, touchedPoints);
2296 mDispatcher->notifyMotion(&motionArgs);
2297 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2298
2299 // Touch Window 2
2300 int32_t actionPointerDown =
2301 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2302 touchedPoints.emplace_back(PointF{150, 150});
2303 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2304
2305 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2306 ADISPLAY_ID_DEFAULT, touchedPoints);
2307 mDispatcher->notifyMotion(&motionArgs);
2308
2309 // Consuming from window1 since it's the window that has the InputReceiver
2310 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2311
2312 // Move both windows
2313 touchedPoints = {{20, 20}, {175, 175}};
2314 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2315 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2316
2317 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2318 ADISPLAY_ID_DEFAULT, touchedPoints);
2319 mDispatcher->notifyMotion(&motionArgs);
2320
2321 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2322}
2323
2324TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2325 mWindow1->setWindowScale(0.5f, 0.5f);
2326
2327 // Touch Window 1
2328 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2329 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
2330
2331 NotifyMotionArgs motionArgs =
2332 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2333 ADISPLAY_ID_DEFAULT, touchedPoints);
2334 mDispatcher->notifyMotion(&motionArgs);
2335 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, expectedPoints);
2336
2337 // Touch Window 2
2338 int32_t actionPointerDown =
2339 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2340 touchedPoints.emplace_back(PointF{150, 150});
2341 expectedPoints.emplace_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2342
2343 motionArgs = generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN,
2344 ADISPLAY_ID_DEFAULT, touchedPoints);
2345 mDispatcher->notifyMotion(&motionArgs);
2346
2347 // Consuming from window1 since it's the window that has the InputReceiver
2348 consumeMotionEvent(mWindow1, actionPointerDown, expectedPoints);
2349
2350 // Move both windows
2351 touchedPoints = {{20, 20}, {175, 175}};
2352 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2353 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2354
2355 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2356 ADISPLAY_ID_DEFAULT, touchedPoints);
2357 mDispatcher->notifyMotion(&motionArgs);
2358
2359 consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_MOVE, expectedPoints);
2360}
2361
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002362class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2363 virtual void SetUp() override {
2364 InputDispatcherTest::SetUp();
2365
2366 mApplication = new FakeApplicationHandle();
2367 mApplication->setDispatchingTimeout(20ms);
2368 mWindow =
2369 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2370 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002371 mWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002372 mWindow->setFocus(true);
2373 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2374 // window.
2375 mWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
2376
2377 // Set focused application.
2378 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2379
2380 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2381 mWindow->consumeFocusEvent(true);
2382 }
2383
2384 virtual void TearDown() override {
2385 InputDispatcherTest::TearDown();
2386 mWindow.clear();
2387 }
2388
2389protected:
2390 sp<FakeApplicationHandle> mApplication;
2391 sp<FakeWindowHandle> mWindow;
2392 static constexpr PointF WINDOW_LOCATION = {20, 20};
2393
2394 void tapOnWindow() {
2395 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2396 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2397 WINDOW_LOCATION));
2398 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2399 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2400 WINDOW_LOCATION));
2401 }
2402};
2403
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002404// Send a tap and respond, which should not cause an ANR.
2405TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2406 tapOnWindow();
2407 mWindow->consumeMotionDown();
2408 mWindow->consumeMotionUp();
2409 ASSERT_TRUE(mDispatcher->waitForIdle());
2410 mFakePolicy->assertNotifyAnrWasNotCalled();
2411}
2412
2413// Send a regular key and respond, which should not cause an ANR.
2414TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
2415 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2416 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2417 ASSERT_TRUE(mDispatcher->waitForIdle());
2418 mFakePolicy->assertNotifyAnrWasNotCalled();
2419}
2420
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002421// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002422// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
2423// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002424TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
2425 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2426 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2427 WINDOW_LOCATION));
2428
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002429 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2430 ASSERT_TRUE(sequenceNum);
2431 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2432 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002433
2434 // The remaining lines are not really needed for the test, but kept as a sanity check
2435 mWindow->finishEvent(*sequenceNum);
2436 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2437 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002438 ASSERT_TRUE(mDispatcher->waitForIdle());
2439}
2440
2441// Send a key to the app and have the app not respond right away.
2442TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
2443 // Inject a key, and don't respond - expect that ANR is called.
2444 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher));
2445 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
2446 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002447 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002448 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002449 ASSERT_TRUE(mDispatcher->waitForIdle());
2450}
2451
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002452// We have a focused application, but no focused window
2453TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
2454 mWindow->setFocus(false);
2455 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2456 mWindow->consumeFocusEvent(false);
2457
2458 // taps on the window work as normal
2459 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2460 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2461 WINDOW_LOCATION));
2462 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
2463 mDispatcher->waitForIdle();
2464 mFakePolicy->assertNotifyAnrWasNotCalled();
2465
2466 // Once a focused event arrives, we get an ANR for this application
2467 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2468 // injection times out (instead of failing).
2469 const int32_t result =
2470 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2471 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2472 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2473 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2474 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2475 ASSERT_TRUE(mDispatcher->waitForIdle());
2476}
2477
2478// We have a focused application, but no focused window
2479// If the policy wants to keep waiting on the focused window to be added, make sure
2480// that this timeout extension is honored and ANR is raised again.
2481TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_ExtendsAnr) {
2482 mWindow->setFocus(false);
2483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2484 mWindow->consumeFocusEvent(false);
2485 const std::chrono::duration timeout = 5ms;
2486 mFakePolicy->setAnrTimeout(timeout);
2487
2488 // Once a focused event arrives, we get an ANR for this application
2489 // We specify the injection timeout to be smaller than the application timeout, to ensure that
2490 // injection times out (instead of failing).
2491 const int32_t result =
2492 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2493 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2494 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2495 const std::chrono::duration appTimeout =
2496 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2497 mFakePolicy->assertNotifyAnrWasCalled(appTimeout, mApplication, nullptr /*windowToken*/);
2498
2499 // After the extended time has passed, ANR should be raised again
2500 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2501
2502 // If we stop extending the timeout, dispatcher should go to idle.
2503 // Another ANR may be raised during this time
2504 mFakePolicy->setAnrTimeout(0ms);
2505 ASSERT_TRUE(mDispatcher->waitForIdle());
2506}
2507
2508// We have a focused application, but no focused window
2509TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
2510 mWindow->setFocus(false);
2511 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2512 mWindow->consumeFocusEvent(false);
2513
2514 // Once a focused event arrives, we get an ANR for this application
2515 const int32_t result =
2516 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2517 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2518 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2519
2520 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2521 mFakePolicy->assertNotifyAnrWasCalled(timeout, mApplication, nullptr /*windowToken*/);
2522
2523 // Future focused events get dropped right away
2524 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, injectKeyDown(mDispatcher));
2525 ASSERT_TRUE(mDispatcher->waitForIdle());
2526 mWindow->assertNoEvents();
2527}
2528
2529/**
2530 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
2531 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
2532 * If we process 1 of the events, but ANR on the second event with the same timestamp,
2533 * the ANR mechanism should still work.
2534 *
2535 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
2536 * DOWN event, while not responding on the second one.
2537 */
2538TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
2539 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
2540 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2541 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2542 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2543 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2544 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2545
2546 // Now send ACTION_UP, with identical timestamp
2547 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2548 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
2549 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
2550 AMOTION_EVENT_INVALID_CURSOR_POSITION},
2551 500ms, INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, currentTime);
2552
2553 // We have now sent down and up. Let's consume first event and then ANR on the second.
2554 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2555 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2556 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2557}
2558
2559// If an app is not responding to a key event, gesture monitors should continue to receive
2560// new motion events
2561TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
2562 FakeMonitorReceiver monitor =
2563 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2564 true /*isGestureMonitor*/);
2565
2566 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
2567 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2568 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
2569
2570 // Stuck on the ACTION_UP
2571 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2572 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2573
2574 // New tap will go to the gesture monitor, but not to the window
2575 tapOnWindow();
2576 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2577 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2578
2579 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2580 mDispatcher->waitForIdle();
2581 mWindow->assertNoEvents();
2582 monitor.assertNoEvents();
2583}
2584
2585// If an app is not responding to a motion event, gesture monitors should continue to receive
2586// new motion events
2587TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
2588 FakeMonitorReceiver monitor =
2589 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2590 true /*isGestureMonitor*/);
2591
2592 tapOnWindow();
2593 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2594 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2595
2596 mWindow->consumeMotionDown();
2597 // Stuck on the ACTION_UP
2598 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2599 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr, mWindow->getToken());
2600
2601 // New tap will go to the gesture monitor, but not to the window
2602 tapOnWindow();
2603 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2604 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
2605
2606 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
2607 mDispatcher->waitForIdle();
2608 mWindow->assertNoEvents();
2609 monitor.assertNoEvents();
2610}
2611
2612// If a window is unresponsive, then you get anr. if the window later catches up and starts to
2613// process events, you don't get an anr. When the window later becomes unresponsive again, you
2614// get an ANR again.
2615// 1. tap -> block on ACTION_UP -> receive ANR
2616// 2. consume all pending events (= queue becomes healthy again)
2617// 3. tap again -> block on ACTION_UP again -> receive ANR second time
2618TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
2619 tapOnWindow();
2620
2621 mWindow->consumeMotionDown();
2622 // Block on ACTION_UP
2623 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2624 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2625 mWindow->consumeMotionUp(); // Now the connection should be healthy again
2626 mDispatcher->waitForIdle();
2627 mWindow->assertNoEvents();
2628
2629 tapOnWindow();
2630 mWindow->consumeMotionDown();
2631 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2632 mWindow->consumeMotionUp();
2633
2634 mDispatcher->waitForIdle();
2635 mWindow->assertNoEvents();
2636}
2637
2638// If the policy tells us to raise ANR again after some time, ensure that the timeout extension
2639// is honored
2640TEST_F(InputDispatcherSingleWindowAnr, Policy_CanExtendTimeout) {
2641 const std::chrono::duration timeout = 5ms;
2642 mFakePolicy->setAnrTimeout(timeout);
2643
2644 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2645 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2646 WINDOW_LOCATION));
2647
2648 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2649 mFakePolicy->assertNotifyAnrWasCalled(windowTimeout, nullptr /*application*/,
2650 mWindow->getToken());
2651
2652 // Since the policy wanted to extend ANR, make sure it is called again after the extension
2653 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/, mWindow->getToken());
2654 mFakePolicy->setAnrTimeout(0ms);
2655 std::this_thread::sleep_for(windowTimeout);
2656 // We are not checking if ANR has been called, because it may have been called again by the
2657 // time we set the timeout to 0
2658
2659 // When the policy finally says stop, we should get ACTION_CANCEL
2660 mWindow->consumeMotionDown();
2661 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2662 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2663 mWindow->assertNoEvents();
2664}
2665
2666/**
2667 * If a window is processing a motion event, and then a key event comes in, the key event should
2668 * not to to the focused window until the motion is processed.
2669 *
2670 * Warning!!!
2671 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
2672 * and the injection timeout that we specify when injecting the key.
2673 * We must have the injection timeout (10ms) be smaller than
2674 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
2675 *
2676 * If that value changes, this test should also change.
2677 */
2678TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
2679 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2680 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2681
2682 tapOnWindow();
2683 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2684 ASSERT_TRUE(downSequenceNum);
2685 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2686 ASSERT_TRUE(upSequenceNum);
2687 // Don't finish the events yet, and send a key
2688 // Injection will "succeed" because we will eventually give up and send the key to the focused
2689 // window even if motions are still being processed. But because the injection timeout is short,
2690 // we will receive INJECTION_TIMED_OUT as the result.
2691
2692 int32_t result =
2693 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
2694 INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT, 10ms);
2695 ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, result);
2696 // Key will not be sent to the window, yet, because the window is still processing events
2697 // and the key remains pending, waiting for the touch events to be processed
2698 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2699 ASSERT_FALSE(keySequenceNum);
2700
2701 std::this_thread::sleep_for(500ms);
2702 // if we wait long enough though, dispatcher will give up, and still send the key
2703 // to the focused window, even though we have not yet finished the motion event
2704 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2705 mWindow->finishEvent(*downSequenceNum);
2706 mWindow->finishEvent(*upSequenceNum);
2707}
2708
2709/**
2710 * If a window is processing a motion event, and then a key event comes in, the key event should
2711 * not go to the focused window until the motion is processed.
2712 * If then a new motion comes in, then the pending key event should be going to the currently
2713 * focused window right away.
2714 */
2715TEST_F(InputDispatcherSingleWindowAnr,
2716 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
2717 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
2718 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2719
2720 tapOnWindow();
2721 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
2722 ASSERT_TRUE(downSequenceNum);
2723 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
2724 ASSERT_TRUE(upSequenceNum);
2725 // Don't finish the events yet, and send a key
2726 // Injection is async, so it will succeed
2727 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2728 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
2729 ADISPLAY_ID_DEFAULT, INPUT_EVENT_INJECTION_SYNC_NONE));
2730 // At this point, key is still pending, and should not be sent to the application yet.
2731 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
2732 ASSERT_FALSE(keySequenceNum);
2733
2734 // Now tap down again. It should cause the pending key to go to the focused window right away.
2735 tapOnWindow();
2736 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
2737 // the other events yet. We can finish events in any order.
2738 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
2739 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
2740 mWindow->consumeMotionDown();
2741 mWindow->consumeMotionUp();
2742 mWindow->assertNoEvents();
2743}
2744
2745class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
2746 virtual void SetUp() override {
2747 InputDispatcherTest::SetUp();
2748
2749 mApplication = new FakeApplicationHandle();
2750 mApplication->setDispatchingTimeout(10ms);
2751 mUnfocusedWindow =
2752 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
2753 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2754 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2755 // window.
2756 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
2757 mUnfocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2758 InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH |
2759 InputWindowInfo::FLAG_SPLIT_TOUCH);
2760
2761 mFocusedWindow =
2762 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002763 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002764 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
2765 mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL |
2766 InputWindowInfo::FLAG_SPLIT_TOUCH);
2767
2768 // Set focused application.
2769 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2770 mFocusedWindow->setFocus(true);
2771
2772 // Expect one focus window exist in display.
2773 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2774 mFocusedWindow->consumeFocusEvent(true);
2775 }
2776
2777 virtual void TearDown() override {
2778 InputDispatcherTest::TearDown();
2779
2780 mUnfocusedWindow.clear();
2781 mFocusedWindow.clear();
2782 }
2783
2784protected:
2785 sp<FakeApplicationHandle> mApplication;
2786 sp<FakeWindowHandle> mUnfocusedWindow;
2787 sp<FakeWindowHandle> mFocusedWindow;
2788 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
2789 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
2790 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
2791
2792 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
2793
2794 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
2795
2796private:
2797 void tap(const PointF& location) {
2798 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2799 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2800 location));
2801 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2802 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2803 location));
2804 }
2805};
2806
2807// If we have 2 windows that are both unresponsive, the one with the shortest timeout
2808// should be ANR'd first.
2809TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
2810 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2811 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2812 FOCUSED_WINDOW_LOCATION))
2813 << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
2814 mFocusedWindow->consumeMotionDown();
2815 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
2816 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2817 // We consumed all events, so no ANR
2818 ASSERT_TRUE(mDispatcher->waitForIdle());
2819 mFakePolicy->assertNotifyAnrWasNotCalled();
2820
2821 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
2822 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2823 FOCUSED_WINDOW_LOCATION));
2824 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
2825 ASSERT_TRUE(unfocusedSequenceNum);
2826 std::optional<uint32_t> focusedSequenceNum = mFocusedWindow->receiveEvent();
2827 ASSERT_TRUE(focusedSequenceNum);
2828
2829 const std::chrono::duration timeout =
2830 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2831 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
2832 mFocusedWindow->getToken());
2833
2834 mFocusedWindow->finishEvent(*focusedSequenceNum);
2835 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
2836 ASSERT_TRUE(mDispatcher->waitForIdle());
2837}
2838
2839// If we have 2 windows with identical timeouts that are both unresponsive,
2840// it doesn't matter which order they should have ANR.
2841// But we should receive ANR for both.
2842TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
2843 // Set the timeout for unfocused window to match the focused window
2844 mUnfocusedWindow->setDispatchingTimeout(10ms);
2845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2846
2847 tapOnFocusedWindow();
2848 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
2849 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData1 =
2850 mFakePolicy->getNotifyAnrData(10ms);
2851 std::pair<sp<InputApplicationHandle>, sp<IBinder>> anrData2 =
2852 mFakePolicy->getNotifyAnrData(0ms);
2853
2854 // We don't know which window will ANR first. But both of them should happen eventually.
2855 ASSERT_TRUE(mFocusedWindow->getToken() == anrData1.second ||
2856 mFocusedWindow->getToken() == anrData2.second);
2857 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrData1.second ||
2858 mUnfocusedWindow->getToken() == anrData2.second);
2859
2860 ASSERT_TRUE(mDispatcher->waitForIdle());
2861 mFakePolicy->assertNotifyAnrWasNotCalled();
2862}
2863
2864// If a window is already not responding, the second tap on the same window should be ignored.
2865// We should also log an error to account for the dropped event (not tested here).
2866// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
2867TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
2868 tapOnFocusedWindow();
2869 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
2870 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2871 // Receive the events, but don't respond
2872 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
2873 ASSERT_TRUE(downEventSequenceNum);
2874 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
2875 ASSERT_TRUE(upEventSequenceNum);
2876 const std::chrono::duration timeout =
2877 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
2878 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
2879 mFocusedWindow->getToken());
2880
2881 // Tap once again
2882 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
2883 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2884 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2885 FOCUSED_WINDOW_LOCATION));
2886 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2887 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2888 FOCUSED_WINDOW_LOCATION));
2889 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
2890 // valid touch target
2891 mUnfocusedWindow->assertNoEvents();
2892
2893 // Consume the first tap
2894 mFocusedWindow->finishEvent(*downEventSequenceNum);
2895 mFocusedWindow->finishEvent(*upEventSequenceNum);
2896 ASSERT_TRUE(mDispatcher->waitForIdle());
2897 // The second tap did not go to the focused window
2898 mFocusedWindow->assertNoEvents();
2899 // should not have another ANR after the window just became healthy again
2900 mFakePolicy->assertNotifyAnrWasNotCalled();
2901}
2902
2903// If you tap outside of all windows, there will not be ANR
2904TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
2905 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2906 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2907 LOCATION_OUTSIDE_ALL_WINDOWS));
2908 ASSERT_TRUE(mDispatcher->waitForIdle());
2909 mFakePolicy->assertNotifyAnrWasNotCalled();
2910}
2911
2912// Since the focused window is paused, tapping on it should not produce any events
2913TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
2914 mFocusedWindow->setPaused(true);
2915 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
2916
2917 ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED,
2918 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2919 FOCUSED_WINDOW_LOCATION));
2920
2921 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
2922 ASSERT_TRUE(mDispatcher->waitForIdle());
2923 // Should not ANR because the window is paused, and touches shouldn't go to it
2924 mFakePolicy->assertNotifyAnrWasNotCalled();
2925
2926 mFocusedWindow->assertNoEvents();
2927 mUnfocusedWindow->assertNoEvents();
2928}
2929
2930/**
2931 * If a window is processing a motion event, and then a key event comes in, the key event should
2932 * not to to the focused window until the motion is processed.
2933 * If a different window becomes focused at this time, the key should go to that window instead.
2934 *
2935 * Warning!!!
2936 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
2937 * and the injection timeout that we specify when injecting the key.
2938 * We must have the injection timeout (10ms) be smaller than
2939 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
2940 *
2941 * If that value changes, this test should also change.
2942 */
2943TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
2944 // Set a long ANR timeout to prevent it from triggering
2945 mFocusedWindow->setDispatchingTimeout(2s);
2946 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
2947
2948 tapOnUnfocusedWindow();
2949 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
2950 ASSERT_TRUE(downSequenceNum);
2951 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
2952 ASSERT_TRUE(upSequenceNum);
2953 // Don't finish the events yet, and send a key
2954 // Injection will succeed because we will eventually give up and send the key to the focused
2955 // window even if motions are still being processed.
2956
2957 int32_t result =
2958 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
2959 INPUT_EVENT_INJECTION_SYNC_NONE, 10ms /*injectionTimeout*/);
2960 ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, result);
2961 // Key will not be sent to the window, yet, because the window is still processing events
2962 // and the key remains pending, waiting for the touch events to be processed
2963 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
2964 ASSERT_FALSE(keySequenceNum);
2965
2966 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
2967 mFocusedWindow->setFocus(false);
2968 mUnfocusedWindow->setFocus(true);
2969 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
2970
2971 // Focus events should precede the key events
2972 mUnfocusedWindow->consumeFocusEvent(true);
2973 mFocusedWindow->consumeFocusEvent(false);
2974
2975 // Finish the tap events, which should unblock dispatcher
2976 mUnfocusedWindow->finishEvent(*downSequenceNum);
2977 mUnfocusedWindow->finishEvent(*upSequenceNum);
2978
2979 // Now that all queues are cleared and no backlog in the connections, the key event
2980 // can finally go to the newly focused "mUnfocusedWindow".
2981 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2982 mFocusedWindow->assertNoEvents();
2983 mUnfocusedWindow->assertNoEvents();
2984}
2985
2986// When the touch stream is split across 2 windows, and one of them does not respond,
2987// then ANR should be raised and the touch should be canceled for the unresponsive window.
2988// The other window should not be affected by that.
2989TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
2990 // Touch Window 1
2991 NotifyMotionArgs motionArgs =
2992 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2993 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
2994 mDispatcher->notifyMotion(&motionArgs);
2995 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
2996 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
2997
2998 // Touch Window 2
2999 int32_t actionPointerDown =
3000 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3001
3002 motionArgs =
3003 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3004 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3005 mDispatcher->notifyMotion(&motionArgs);
3006
3007 const std::chrono::duration timeout =
3008 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
3009 mFakePolicy->assertNotifyAnrWasCalled(timeout, nullptr /*application*/,
3010 mFocusedWindow->getToken());
3011
3012 mUnfocusedWindow->consumeMotionDown();
3013 mFocusedWindow->consumeMotionDown();
3014 // Focused window may or may not receive ACTION_MOVE
3015 // But it should definitely receive ACTION_CANCEL due to the ANR
3016 InputEvent* event;
3017 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3018 ASSERT_TRUE(moveOrCancelSequenceNum);
3019 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3020 ASSERT_NE(nullptr, event);
3021 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3022 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3023 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3024 mFocusedWindow->consumeMotionCancel();
3025 } else {
3026 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3027 }
3028
3029 ASSERT_TRUE(mDispatcher->waitForIdle());
3030 mUnfocusedWindow->assertNoEvents();
3031 mFocusedWindow->assertNoEvents();
3032}
3033
Garfield Tane84e6f92019-08-29 17:28:41 -07003034} // namespace android::inputdispatcher