blob: 76328148c24a76f9b749aefe1d361c340dc3e183 [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;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080032using android::os::InputEventInjectionResult;
33using android::os::InputEventInjectionSync;
Michael Wright44753b12020-07-08 13:48:11 +010034using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080035
Garfield Tane84e6f92019-08-29 17:28:41 -070036namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080037
38// An arbitrary time value.
39static const nsecs_t ARBITRARY_TIME = 1234;
40
41// An arbitrary device id.
42static const int32_t DEVICE_ID = 1;
43
Jeff Brownf086ddb2014-02-11 14:28:48 -080044// An arbitrary display id.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -080045static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
Jeff Brownf086ddb2014-02-11 14:28:48 -080046
Michael Wrightd02c5b62014-02-10 15:10:22 -080047// An arbitrary injector pid / uid pair that has permission to inject events.
48static const int32_t INJECTOR_PID = 999;
49static const int32_t INJECTOR_UID = 1001;
50
chaviwd1c23182019-12-20 18:44:56 -080051struct PointF {
52 float x;
53 float y;
54};
Michael Wrightd02c5b62014-02-10 15:10:22 -080055
Gang Wang342c9272020-01-13 13:15:04 -050056/**
57 * Return a DOWN key event with KEYCODE_A.
58 */
59static KeyEvent getTestKeyEvent() {
60 KeyEvent event;
61
Garfield Tanfbe732e2020-01-24 11:26:14 -080062 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
63 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
64 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050065 return event;
66}
67
Michael Wrightd02c5b62014-02-10 15:10:22 -080068// --- FakeInputDispatcherPolicy ---
69
70class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
71 InputDispatcherConfiguration mConfig;
72
73protected:
74 virtual ~FakeInputDispatcherPolicy() {
75 }
76
77public:
78 FakeInputDispatcherPolicy() {
Jackal Guof9696682018-10-05 12:23:23 +080079 }
80
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080081 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080082 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
83 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080084 }
85
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080086 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080087 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
88 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080089 }
90
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070091 void assertFilterInputEventWasNotCalled() {
92 std::scoped_lock lock(mLock);
93 ASSERT_EQ(nullptr, mFilteredEvent);
94 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080095
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080096 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070097 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080098 ASSERT_TRUE(mConfigurationChangedTime)
99 << "Timed out waiting for configuration changed call";
100 ASSERT_EQ(*mConfigurationChangedTime, when);
101 mConfigurationChangedTime = std::nullopt;
102 }
103
104 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700105 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800106 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800107 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800108 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
109 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
110 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
111 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
112 mLastNotifySwitch = std::nullopt;
113 }
114
chaviwfd6d3512019-03-25 13:23:49 -0700115 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700116 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800117 ASSERT_EQ(touchedToken, mOnPointerDownToken);
118 mOnPointerDownToken.clear();
119 }
120
121 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700122 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800123 ASSERT_TRUE(mOnPointerDownToken == nullptr)
124 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700125 }
126
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700127 // This function must be called soon after the expected ANR timer starts,
128 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500129 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700130 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500131 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
132 std::shared_ptr<InputApplicationHandle> application;
133 { // acquire lock
134 std::unique_lock lock(mLock);
135 android::base::ScopedLockAssertion assumeLocked(mLock);
136 ASSERT_NO_FATAL_FAILURE(
137 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
138 } // release lock
139 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700140 }
141
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500142 void assertNotifyConnectionUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
143 const sp<IBinder>& expectedConnectionToken) {
144 sp<IBinder> connectionToken = getUnresponsiveConnectionToken(timeout);
145 ASSERT_EQ(expectedConnectionToken, connectionToken);
146 }
147
148 void assertNotifyConnectionResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
149 sp<IBinder> connectionToken = getResponsiveConnectionToken();
150 ASSERT_EQ(expectedConnectionToken, connectionToken);
151 }
152
153 sp<IBinder> getUnresponsiveConnectionToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700154 std::unique_lock lock(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700155 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500156 return getAnrTokenLockedInterruptible(timeout, mAnrConnectionTokens, lock);
157 }
158
159 sp<IBinder> getResponsiveConnectionToken() {
160 std::unique_lock lock(mLock);
161 android::base::ScopedLockAssertion assumeLocked(mLock);
162 return getAnrTokenLockedInterruptible(0s, mResponsiveConnectionTokens, lock);
163 }
164
165 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
166 // for a specific container to become non-empty. When the container is non-empty, return the
167 // first entry from the container and erase it.
168 template <class T>
169 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
170 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
171 const std::chrono::time_point start = std::chrono::steady_clock::now();
172 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700173
174 // If there is an ANR, Dispatcher won't be idle because there are still events
175 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
176 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500177 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
178 // to provide it some time to act. 100ms seems reasonable.
179 mNotifyAnr.wait_for(lock, timeToWait,
180 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700181 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500182 if (storage.empty()) {
183 ADD_FAILURE() << "Did not receive the ANR callback";
184 return nullptr;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700185 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700186 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
187 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700188 if (std::chrono::abs(timeout - waited) > 100ms) {
189 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
190 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
191 << "ms, but waited "
192 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
193 << "ms instead";
194 }
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500195 T token = storage.front();
196 storage.pop();
197 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700198 }
199
200 void assertNotifyAnrWasNotCalled() {
201 std::scoped_lock lock(mLock);
202 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500203 ASSERT_TRUE(mAnrConnectionTokens.empty());
204 ASSERT_TRUE(mResponsiveConnectionTokens.empty())
205 << "ANR was not called, but please also consume the 'connection is responsive' "
206 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700207 }
208
Garfield Tan1c7bc862020-01-28 13:24:04 -0800209 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
210 mConfig.keyRepeatTimeout = timeout;
211 mConfig.keyRepeatDelay = delay;
212 }
213
Prabir Pradhan99987712020-11-10 18:43:05 -0800214 void waitForSetPointerCapture(bool enabled) {
215 std::unique_lock lock(mLock);
216 base::ScopedLockAssertion assumeLocked(mLock);
217
218 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
219 [this, enabled]() REQUIRES(mLock) {
220 return mPointerCaptureEnabled &&
221 *mPointerCaptureEnabled ==
222 enabled;
223 })) {
224 FAIL() << "Timed out waiting for setPointerCapture(" << enabled << ") to be called.";
225 }
226 mPointerCaptureEnabled.reset();
227 }
228
229 void assertSetPointerCaptureNotCalled() {
230 std::unique_lock lock(mLock);
231 base::ScopedLockAssertion assumeLocked(mLock);
232
233 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
234 FAIL() << "Expected setPointerCapture(enabled) to not be called, but was called. "
235 "enabled = "
236 << *mPointerCaptureEnabled;
237 }
238 mPointerCaptureEnabled.reset();
239 }
240
Michael Wrightd02c5b62014-02-10 15:10:22 -0800241private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700242 std::mutex mLock;
243 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
244 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
245 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
246 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800247
Prabir Pradhan99987712020-11-10 18:43:05 -0800248 std::condition_variable mPointerCaptureChangedCondition;
249 std::optional<bool> mPointerCaptureEnabled GUARDED_BY(mLock);
250
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700251 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700252 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500253 std::queue<sp<IBinder>> mAnrConnectionTokens GUARDED_BY(mLock);
254 std::queue<sp<IBinder>> mResponsiveConnectionTokens GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700255 std::condition_variable mNotifyAnr;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700256
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600257 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700258 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800259 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800260 }
261
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500262 void notifyConnectionUnresponsive(const sp<IBinder>& connectionToken,
263 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700264 std::scoped_lock lock(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500265 mAnrConnectionTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700266 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500267 }
268
269 void notifyConnectionResponsive(const sp<IBinder>& connectionToken) override {
270 std::scoped_lock lock(mLock);
271 mResponsiveConnectionTokens.push(connectionToken);
272 mNotifyAnr.notify_all();
273 }
274
275 void notifyNoFocusedWindowAnr(
276 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
277 std::scoped_lock lock(mLock);
278 mAnrApplications.push(applicationHandle);
279 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800280 }
281
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600282 void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800283
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600284 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700285
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600286 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000287
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600288 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800289 *outConfig = mConfig;
290 }
291
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600292 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700293 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800294 switch (inputEvent->getType()) {
295 case AINPUT_EVENT_TYPE_KEY: {
296 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800297 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800298 break;
299 }
300
301 case AINPUT_EVENT_TYPE_MOTION: {
302 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800303 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800304 break;
305 }
306 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800307 return true;
308 }
309
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600310 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800311
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600312 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600314 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800315 return 0;
316 }
317
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600318 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800319 return false;
320 }
321
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600322 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
323 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700324 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800325 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
326 * essentially a passthrough for notifySwitch.
327 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800328 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800329 }
330
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600331 void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800332
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600333 bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; }
Jackal Guof9696682018-10-05 12:23:23 +0800334
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600335 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700336 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700337 mOnPointerDownToken = newToken;
338 }
339
Prabir Pradhan99987712020-11-10 18:43:05 -0800340 void setPointerCapture(bool enabled) override {
341 std::scoped_lock lock(mLock);
342 mPointerCaptureEnabled = {enabled};
343 mPointerCaptureChangedCondition.notify_all();
344 }
345
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800346 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
347 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700348 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800349 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
350 ASSERT_EQ(mFilteredEvent->getType(), type);
351
352 if (type == AINPUT_EVENT_TYPE_KEY) {
353 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
354 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
355 EXPECT_EQ(keyEvent.getAction(), action);
356 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
357 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
358 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
359 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
360 EXPECT_EQ(motionEvent.getAction(), action);
361 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
362 } else {
363 FAIL() << "Unknown type: " << type;
364 }
365
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800366 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800367 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800368};
369
Michael Wrightd02c5b62014-02-10 15:10:22 -0800370// --- InputDispatcherTest ---
371
372class InputDispatcherTest : public testing::Test {
373protected:
374 sp<FakeInputDispatcherPolicy> mFakePolicy;
375 sp<InputDispatcher> mDispatcher;
376
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700377 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800378 mFakePolicy = new FakeInputDispatcherPolicy();
379 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800380 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
381 //Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700382 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800383 }
384
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700385 virtual void TearDown() override {
386 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800387 mFakePolicy.clear();
388 mDispatcher.clear();
389 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700390
391 /**
392 * Used for debugging when writing the test
393 */
394 void dumpDispatcherState() {
395 std::string dump;
396 mDispatcher->dump(dump);
397 std::stringstream ss(dump);
398 std::string to;
399
400 while (std::getline(ss, to, '\n')) {
401 ALOGE("%s", to.c_str());
402 }
403 }
Vishnu Nair958da932020-08-21 17:12:37 -0700404
405 void setFocusedWindow(const sp<InputWindowHandle>& window,
406 const sp<InputWindowHandle>& focusedWindow = nullptr) {
407 FocusRequest request;
408 request.token = window->getToken();
409 if (focusedWindow) {
410 request.focusedToken = focusedWindow->getToken();
411 }
412 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
413 request.displayId = window->getInfo()->displayId;
414 mDispatcher->setFocusedWindow(request);
415 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800416};
417
418
419TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
420 KeyEvent event;
421
422 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800423 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
424 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600425 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
426 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800427 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700428 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800429 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800430 << "Should reject key events with undefined action.";
431
432 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800433 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
434 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600435 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800436 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700437 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800438 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800439 << "Should reject key events with ACTION_MULTIPLE.";
440}
441
442TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
443 MotionEvent event;
444 PointerProperties pointerProperties[MAX_POINTERS + 1];
445 PointerCoords pointerCoords[MAX_POINTERS + 1];
446 for (int i = 0; i <= MAX_POINTERS; i++) {
447 pointerProperties[i].clear();
448 pointerProperties[i].id = i;
449 pointerCoords[i].clear();
450 }
451
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800452 // Some constants commonly used below
453 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
454 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
455 constexpr int32_t metaState = AMETA_NONE;
456 constexpr MotionClassification classification = MotionClassification::NONE;
457
chaviw9eaa22c2020-07-01 16:21:27 -0700458 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800459 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800460 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700461 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
462 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600463 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700464 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800465 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700466 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800467 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800468 << "Should reject motion events with undefined action.";
469
470 // Rejects pointer down 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_DOWN |
473 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700474 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
475 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
476 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
477 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800478 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700479 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800480 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 << "Should reject motion events with pointer down 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_DOWN |
485 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700486 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
487 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
488 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
489 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800490 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700491 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800492 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800493 << "Should reject motion events with pointer down index too small.";
494
495 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800496 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700497 AMOTION_EVENT_ACTION_POINTER_UP |
498 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700499 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
500 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
501 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
502 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800503 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700504 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800505 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800506 << "Should reject motion events with pointer up index too large.";
507
Garfield Tanfbe732e2020-01-24 11:26:14 -0800508 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700509 AMOTION_EVENT_ACTION_POINTER_UP |
510 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700511 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
512 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
513 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
514 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800515 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700516 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800517 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800518 << "Should reject motion events with pointer up index too small.";
519
520 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800521 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
522 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700523 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
524 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700525 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800526 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700527 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800528 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800529 << "Should reject motion events with 0 pointers.";
530
Garfield Tanfbe732e2020-01-24 11:26:14 -0800531 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
532 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700533 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
534 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700535 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800536 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700537 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800538 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800539 << "Should reject motion events with more than MAX_POINTERS pointers.";
540
541 // Rejects motion events with invalid pointer ids.
542 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800543 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
544 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700545 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
546 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700547 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800548 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700549 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800550 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551 << "Should reject motion events with pointer ids less than 0.";
552
553 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800554 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
555 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700556 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
557 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700558 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800559 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700560 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800561 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800562 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
563
564 // Rejects motion events with duplicate pointer ids.
565 pointerProperties[0].id = 1;
566 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800567 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
568 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700569 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
570 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700571 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800572 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700573 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800574 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800575 << "Should reject motion events with duplicate pointer ids.";
576}
577
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800578/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
579
580TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
581 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800582 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800583 mDispatcher->notifyConfigurationChanged(&args);
584 ASSERT_TRUE(mDispatcher->waitForIdle());
585
586 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
587}
588
589TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800590 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
591 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800592 mDispatcher->notifySwitch(&args);
593
594 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
595 args.policyFlags |= POLICY_FLAG_TRUSTED;
596 mFakePolicy->assertNotifySwitchWasCalled(args);
597}
598
Arthur Hungb92218b2018-08-14 12:00:21 +0800599// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700600static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700601static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800602
603class FakeApplicationHandle : public InputApplicationHandle {
604public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700605 FakeApplicationHandle() {
606 mInfo.name = "Fake Application";
607 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500608 mInfo.dispatchingTimeoutMillis =
609 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700610 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800611 virtual ~FakeApplicationHandle() {}
612
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700613 virtual bool updateInfo() override {
Arthur Hungb92218b2018-08-14 12:00:21 +0800614 return true;
615 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700616
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500617 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
618 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700619 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800620};
621
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800622class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800623public:
Garfield Tan15601662020-09-22 15:32:38 -0700624 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800625 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700626 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800627 }
628
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800629 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700630 InputEvent* event;
631 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
632 if (!consumeSeq) {
633 return nullptr;
634 }
635 finishEvent(*consumeSeq);
636 return event;
637 }
638
639 /**
640 * Receive an event without acknowledging it.
641 * Return the sequence number that could later be used to send finished signal.
642 */
643 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800644 uint32_t consumeSeq;
645 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800646
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800647 std::chrono::time_point start = std::chrono::steady_clock::now();
648 status_t status = WOULD_BLOCK;
649 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800650 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800651 &event);
652 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
653 if (elapsed > 100ms) {
654 break;
655 }
656 }
657
658 if (status == WOULD_BLOCK) {
659 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700660 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800661 }
662
663 if (status != OK) {
664 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700665 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800666 }
667 if (event == nullptr) {
668 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700669 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800670 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700671 if (outEvent != nullptr) {
672 *outEvent = event;
673 }
674 return consumeSeq;
675 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800676
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700677 /**
678 * To be used together with "receiveEvent" to complete the consumption of an event.
679 */
680 void finishEvent(uint32_t consumeSeq) {
681 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
682 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800683 }
684
685 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
686 int32_t expectedFlags) {
687 InputEvent* event = consume();
688
689 ASSERT_NE(nullptr, event) << mName.c_str()
690 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800691 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700692 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800693 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800694
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800695 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800696
Tiger Huang8664f8c2018-10-11 19:14:35 +0800697 switch (expectedEventType) {
698 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800699 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
700 EXPECT_EQ(expectedAction, keyEvent.getAction());
701 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800702 break;
703 }
704 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800705 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
706 EXPECT_EQ(expectedAction, motionEvent.getAction());
707 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800708 break;
709 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100710 case AINPUT_EVENT_TYPE_FOCUS: {
711 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
712 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800713 case AINPUT_EVENT_TYPE_CAPTURE: {
714 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
715 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800716 default: {
717 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
718 }
719 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800720 }
721
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100722 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
723 InputEvent* event = consume();
724 ASSERT_NE(nullptr, event) << mName.c_str()
725 << ": consumer should have returned non-NULL event.";
726 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
727 << "Got " << inputEventTypeToString(event->getType())
728 << " event instead of FOCUS event";
729
730 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
731 << mName.c_str() << ": event displayId should always be NONE.";
732
733 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
734 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
735 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
736 }
737
Prabir Pradhan99987712020-11-10 18:43:05 -0800738 void consumeCaptureEvent(bool hasCapture) {
739 const InputEvent* event = consume();
740 ASSERT_NE(nullptr, event) << mName.c_str()
741 << ": consumer should have returned non-NULL event.";
742 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
743 << "Got " << inputEventTypeToString(event->getType())
744 << " event instead of CAPTURE event";
745
746 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
747 << mName.c_str() << ": event displayId should always be NONE.";
748
749 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
750 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
751 }
752
chaviwd1c23182019-12-20 18:44:56 -0800753 void assertNoEvents() {
754 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700755 if (event == nullptr) {
756 return;
757 }
758 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
759 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
760 ADD_FAILURE() << "Received key event "
761 << KeyEvent::actionToString(keyEvent.getAction());
762 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
763 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
764 ADD_FAILURE() << "Received motion event "
765 << MotionEvent::actionToString(motionEvent.getAction());
766 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
767 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
768 ADD_FAILURE() << "Received focus event, hasFocus = "
769 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800770 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
771 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
772 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
773 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700774 }
775 FAIL() << mName.c_str()
776 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800777 }
778
779 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
780
781protected:
782 std::unique_ptr<InputConsumer> mConsumer;
783 PreallocatedInputEventFactory mEventFactory;
784
785 std::string mName;
786};
787
788class FakeWindowHandle : public InputWindowHandle {
789public:
790 static const int32_t WIDTH = 600;
791 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800792
Chris Yea209fde2020-07-22 13:54:51 -0700793 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800794 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500795 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800796 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500797 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700798 base::Result<std::unique_ptr<InputChannel>> channel =
799 dispatcher->createInputChannel(name);
800 token = (*channel)->getConnectionToken();
801 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800802 }
803
804 inputApplicationHandle->updateInfo();
805 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
806
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500807 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700808 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800809 mInfo.name = name;
Michael Wright44753b12020-07-08 13:48:11 +0100810 mInfo.type = InputWindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500811 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwd1c23182019-12-20 18:44:56 -0800812 mInfo.frameLeft = 0;
813 mInfo.frameTop = 0;
814 mInfo.frameRight = WIDTH;
815 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700816 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800817 mInfo.globalScaleFactor = 1.0;
818 mInfo.touchableRegion.clear();
819 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
820 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700821 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800822 mInfo.hasWallpaper = false;
823 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800824 mInfo.ownerPid = INJECTOR_PID;
825 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800826 mInfo.displayId = displayId;
827 }
828
829 virtual bool updateInfo() { return true; }
830
Vishnu Nair47074b82020-08-14 11:54:47 -0700831 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800832
Vishnu Nair958da932020-08-21 17:12:37 -0700833 void setVisible(bool visible) { mInfo.visible = visible; }
834
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700835 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500836 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700837 }
838
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700839 void setPaused(bool paused) { mInfo.paused = paused; }
840
chaviwd1c23182019-12-20 18:44:56 -0800841 void setFrame(const Rect& frame) {
842 mInfo.frameLeft = frame.left;
843 mInfo.frameTop = frame.top;
844 mInfo.frameRight = frame.right;
845 mInfo.frameBottom = frame.bottom;
chaviw1ff3d1e2020-07-01 15:53:47 -0700846 mInfo.transform.set(frame.left, frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800847 mInfo.touchableRegion.clear();
848 mInfo.addTouchableRegion(frame);
849 }
850
Michael Wright44753b12020-07-08 13:48:11 +0100851 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800852
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500853 void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
854
chaviw9eaa22c2020-07-01 16:21:27 -0700855 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
856 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
857 }
858
859 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700860
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800861 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
862 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
863 expectedFlags);
864 }
865
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700866 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
867 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
868 }
869
Svet Ganov5d3bc372020-01-26 23:11:07 -0800870 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
871 int32_t expectedFlags = 0) {
872 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
873 expectedFlags);
874 }
875
876 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
877 int32_t expectedFlags = 0) {
878 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
879 expectedFlags);
880 }
881
882 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
883 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800884 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
885 expectedFlags);
886 }
887
Svet Ganov5d3bc372020-01-26 23:11:07 -0800888 void consumeMotionPointerDown(int32_t pointerIdx,
889 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) {
890 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN
891 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
892 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
893 }
894
895 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
896 int32_t expectedFlags = 0) {
897 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP
898 | (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
899 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
900 }
901
902 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
903 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000904 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
905 expectedFlags);
906 }
907
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500908 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
909 int32_t expectedFlags = 0) {
910 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
911 expectedFlags);
912 }
913
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100914 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
915 ASSERT_NE(mInputReceiver, nullptr)
916 << "Cannot consume events from a window with no receiver";
917 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
918 }
919
Prabir Pradhan99987712020-11-10 18:43:05 -0800920 void consumeCaptureEvent(bool hasCapture) {
921 ASSERT_NE(mInputReceiver, nullptr)
922 << "Cannot consume events from a window with no receiver";
923 mInputReceiver->consumeCaptureEvent(hasCapture);
924 }
925
chaviwd1c23182019-12-20 18:44:56 -0800926 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
927 int32_t expectedFlags) {
928 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
929 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
930 expectedFlags);
931 }
932
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700933 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700934 if (mInputReceiver == nullptr) {
935 ADD_FAILURE() << "Invalid receive event on window with no receiver";
936 return std::nullopt;
937 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700938 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700939 }
940
941 void finishEvent(uint32_t sequenceNum) {
942 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
943 mInputReceiver->finishEvent(sequenceNum);
944 }
945
chaviwaf87b3e2019-10-01 16:59:28 -0700946 InputEvent* consume() {
947 if (mInputReceiver == nullptr) {
948 return nullptr;
949 }
950 return mInputReceiver->consume();
951 }
952
Arthur Hungb92218b2018-08-14 12:00:21 +0800953 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500954 if (mInputReceiver == nullptr &&
955 mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
956 return; // Can't receive events if the window does not have input channel
957 }
958 ASSERT_NE(nullptr, mInputReceiver)
959 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -0800960 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800961 }
962
chaviwaf87b3e2019-10-01 16:59:28 -0700963 sp<IBinder> getToken() { return mInfo.token; }
964
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100965 const std::string& getName() { return mName; }
966
chaviwd1c23182019-12-20 18:44:56 -0800967private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100968 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800969 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700970 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800971};
972
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700973std::atomic<int32_t> FakeWindowHandle::sId{1};
974
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800975static InputEventInjectionResult injectKey(
976 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
977 int32_t displayId = ADISPLAY_ID_NONE,
978 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
979 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800980 KeyEvent event;
981 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
982
983 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800984 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700985 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
986 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800987
988 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700989 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
990 injectionTimeout,
991 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800992}
993
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800994static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
995 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700996 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
997}
998
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800999static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
1000 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001001 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1002}
1003
Garfield Tandf26e862020-07-01 20:18:19 -07001004class PointerBuilder {
1005public:
1006 PointerBuilder(int32_t id, int32_t toolType) {
1007 mProperties.clear();
1008 mProperties.id = id;
1009 mProperties.toolType = toolType;
1010 mCoords.clear();
1011 }
1012
1013 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1014
1015 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1016
1017 PointerBuilder& axis(int32_t axis, float value) {
1018 mCoords.setAxisValue(axis, value);
1019 return *this;
1020 }
1021
1022 PointerProperties buildProperties() const { return mProperties; }
1023
1024 PointerCoords buildCoords() const { return mCoords; }
1025
1026private:
1027 PointerProperties mProperties;
1028 PointerCoords mCoords;
1029};
1030
1031class MotionEventBuilder {
1032public:
1033 MotionEventBuilder(int32_t action, int32_t source) {
1034 mAction = action;
1035 mSource = source;
1036 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1037 }
1038
1039 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1040 mEventTime = eventTime;
1041 return *this;
1042 }
1043
1044 MotionEventBuilder& displayId(int32_t displayId) {
1045 mDisplayId = displayId;
1046 return *this;
1047 }
1048
1049 MotionEventBuilder& actionButton(int32_t actionButton) {
1050 mActionButton = actionButton;
1051 return *this;
1052 }
1053
1054 MotionEventBuilder& buttonState(int32_t actionButton) {
1055 mActionButton = actionButton;
1056 return *this;
1057 }
1058
1059 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1060 mRawXCursorPosition = rawXCursorPosition;
1061 return *this;
1062 }
1063
1064 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1065 mRawYCursorPosition = rawYCursorPosition;
1066 return *this;
1067 }
1068
1069 MotionEventBuilder& pointer(PointerBuilder pointer) {
1070 mPointers.push_back(pointer);
1071 return *this;
1072 }
1073
1074 MotionEvent build() {
1075 std::vector<PointerProperties> pointerProperties;
1076 std::vector<PointerCoords> pointerCoords;
1077 for (const PointerBuilder& pointer : mPointers) {
1078 pointerProperties.push_back(pointer.buildProperties());
1079 pointerCoords.push_back(pointer.buildCoords());
1080 }
1081
1082 // Set mouse cursor position for the most common cases to avoid boilerplate.
1083 if (mSource == AINPUT_SOURCE_MOUSE &&
1084 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1085 mPointers.size() == 1) {
1086 mRawXCursorPosition = pointerCoords[0].getX();
1087 mRawYCursorPosition = pointerCoords[0].getY();
1088 }
1089
1090 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001091 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001092 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
1093 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001094 mButtonState, MotionClassification::NONE, identityTransform,
1095 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
1096 mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
1097 pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001098
1099 return event;
1100 }
1101
1102private:
1103 int32_t mAction;
1104 int32_t mSource;
1105 nsecs_t mEventTime;
1106 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1107 int32_t mActionButton{0};
1108 int32_t mButtonState{0};
1109 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1110 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1111
1112 std::vector<PointerBuilder> mPointers;
1113};
1114
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001115static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001116 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1117 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001118 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001119 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1120 injectionTimeout,
1121 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1122}
1123
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001124static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001125 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1126 const PointF& position,
1127 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001128 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1129 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001130 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001131 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001132 MotionEvent event = MotionEventBuilder(action, source)
1133 .displayId(displayId)
1134 .eventTime(eventTime)
1135 .rawXCursorPosition(cursorPosition.x)
1136 .rawYCursorPosition(cursorPosition.y)
1137 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1138 .x(position.x)
1139 .y(position.y))
1140 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001141
1142 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001143 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001144}
1145
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001146static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1147 int32_t source, int32_t displayId,
1148 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001149 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001150}
1151
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001152static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1153 int32_t source, int32_t displayId,
1154 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001155 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001156}
1157
Jackal Guof9696682018-10-05 12:23:23 +08001158static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1159 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1160 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001161 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
1162 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
1163 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001164
1165 return args;
1166}
1167
chaviwd1c23182019-12-20 18:44:56 -08001168static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1169 const std::vector<PointF>& points) {
1170 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001171 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1172 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1173 }
1174
chaviwd1c23182019-12-20 18:44:56 -08001175 PointerProperties pointerProperties[pointerCount];
1176 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001177
chaviwd1c23182019-12-20 18:44:56 -08001178 for (size_t i = 0; i < pointerCount; i++) {
1179 pointerProperties[i].clear();
1180 pointerProperties[i].id = i;
1181 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001182
chaviwd1c23182019-12-20 18:44:56 -08001183 pointerCoords[i].clear();
1184 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1185 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1186 }
Jackal Guof9696682018-10-05 12:23:23 +08001187
1188 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1189 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001190 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001191 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1192 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001193 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1194 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001195 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1196 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001197
1198 return args;
1199}
1200
chaviwd1c23182019-12-20 18:44:56 -08001201static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1202 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1203}
1204
Prabir Pradhan99987712020-11-10 18:43:05 -08001205static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(bool enabled) {
1206 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), enabled);
1207}
1208
Arthur Hungb92218b2018-08-14 12:00:21 +08001209TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001210 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001211 sp<FakeWindowHandle> window = new FakeWindowHandle(application, mDispatcher, "Fake Window",
1212 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001213
Arthur Hung72d8dc32020-03-28 00:48:39 +00001214 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1216 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1217 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001218
1219 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001220 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001221}
1222
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001223/**
1224 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1225 * To ensure that window receives only events that were directly inside of it, add
1226 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1227 * when finding touched windows.
1228 * This test serves as a sanity check for the next test, where setInputWindows is
1229 * called twice.
1230 */
1231TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001232 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001233 sp<FakeWindowHandle> window =
1234 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1235 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001236 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001237
1238 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001240 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1241 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001242 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001243
1244 // Window should receive motion event.
1245 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1246}
1247
1248/**
1249 * Calling setInputWindows twice, with the same info, should not cause any issues.
1250 * To ensure that window receives only events that were directly inside of it, add
1251 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1252 * when finding touched windows.
1253 */
1254TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001256 sp<FakeWindowHandle> window =
1257 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1258 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001259 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001260
1261 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1262 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001264 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1265 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001266 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001267
1268 // Window should receive motion event.
1269 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1270}
1271
Arthur Hungb92218b2018-08-14 12:00:21 +08001272// The foreground window should receive the first touch down event.
1273TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001274 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001275 sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
1276 ADISPLAY_ID_DEFAULT);
1277 sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
1278 ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001279
Arthur Hung72d8dc32020-03-28 00:48:39 +00001280 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1282 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1283 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001284
1285 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001286 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001287 windowSecond->assertNoEvents();
1288}
1289
Garfield Tandf26e862020-07-01 20:18:19 -07001290TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001291 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001292 sp<FakeWindowHandle> windowLeft =
1293 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1294 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001295 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001296 sp<FakeWindowHandle> windowRight =
1297 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1298 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001299 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001300
1301 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1302
1303 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1304
1305 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001307 injectMotionEvent(mDispatcher,
1308 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1309 AINPUT_SOURCE_MOUSE)
1310 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1311 .x(900)
1312 .y(400))
1313 .build()));
1314 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1315 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1316 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1317 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1318
1319 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001321 injectMotionEvent(mDispatcher,
1322 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1323 AINPUT_SOURCE_MOUSE)
1324 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1325 .x(300)
1326 .y(400))
1327 .build()));
1328 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1329 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1330 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1331 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1332 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1333 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1334
1335 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001337 injectMotionEvent(mDispatcher,
1338 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1339 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1340 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1341 .x(300)
1342 .y(400))
1343 .build()));
1344 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1345
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001347 injectMotionEvent(mDispatcher,
1348 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1349 AINPUT_SOURCE_MOUSE)
1350 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1351 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1352 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1353 .x(300)
1354 .y(400))
1355 .build()));
1356 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1357 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1358
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001360 injectMotionEvent(mDispatcher,
1361 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1362 AINPUT_SOURCE_MOUSE)
1363 .buttonState(0)
1364 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1365 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1366 .x(300)
1367 .y(400))
1368 .build()));
1369 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1370 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1371
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001373 injectMotionEvent(mDispatcher,
1374 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1375 .buttonState(0)
1376 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1377 .x(300)
1378 .y(400))
1379 .build()));
1380 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1381
1382 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001384 injectMotionEvent(mDispatcher,
1385 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1386 AINPUT_SOURCE_MOUSE)
1387 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1388 .x(900)
1389 .y(400))
1390 .build()));
1391 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1392 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1393 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1394 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1395 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1396 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1397}
1398
1399// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1400// directly in this test.
1401TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001402 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001403 sp<FakeWindowHandle> window =
1404 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1405 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001406 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001407
1408 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1409
1410 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1411
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001413 injectMotionEvent(mDispatcher,
1414 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1415 AINPUT_SOURCE_MOUSE)
1416 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1417 .x(300)
1418 .y(400))
1419 .build()));
1420 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1421 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1422
1423 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001425 injectMotionEvent(mDispatcher,
1426 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1427 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1428 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1429 .x(300)
1430 .y(400))
1431 .build()));
1432 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1433
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001435 injectMotionEvent(mDispatcher,
1436 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1437 AINPUT_SOURCE_MOUSE)
1438 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1439 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1440 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1441 .x(300)
1442 .y(400))
1443 .build()));
1444 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1445 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1446
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001448 injectMotionEvent(mDispatcher,
1449 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1450 AINPUT_SOURCE_MOUSE)
1451 .buttonState(0)
1452 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1453 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1454 .x(300)
1455 .y(400))
1456 .build()));
1457 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1458 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1459
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001461 injectMotionEvent(mDispatcher,
1462 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1463 .buttonState(0)
1464 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1465 .x(300)
1466 .y(400))
1467 .build()));
1468 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1469
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001471 injectMotionEvent(mDispatcher,
1472 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1473 AINPUT_SOURCE_MOUSE)
1474 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1475 .x(300)
1476 .y(400))
1477 .build()));
1478 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1479 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1480}
1481
Garfield Tan00f511d2019-06-12 16:55:40 -07001482TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001483 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001484
1485 sp<FakeWindowHandle> windowLeft =
1486 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1487 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001488 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001489 sp<FakeWindowHandle> windowRight =
1490 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1491 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001492 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001493
1494 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1495
Arthur Hung72d8dc32020-03-28 00:48:39 +00001496 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001497
1498 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1499 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001501 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001502 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001503 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001504 windowRight->assertNoEvents();
1505}
1506
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001507TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001509 sp<FakeWindowHandle> window =
1510 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001511 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001512
Arthur Hung72d8dc32020-03-28 00:48:39 +00001513 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001514 setFocusedWindow(window);
1515
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001516 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001517
1518 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1519 mDispatcher->notifyKey(&keyArgs);
1520
1521 // Window should receive key down event.
1522 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1523
1524 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1525 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001526 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001527 mDispatcher->notifyDeviceReset(&args);
1528 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1529 AKEY_EVENT_FLAG_CANCELED);
1530}
1531
1532TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001534 sp<FakeWindowHandle> window =
1535 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1536
Arthur Hung72d8dc32020-03-28 00:48:39 +00001537 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001538
1539 NotifyMotionArgs motionArgs =
1540 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1541 ADISPLAY_ID_DEFAULT);
1542 mDispatcher->notifyMotion(&motionArgs);
1543
1544 // Window should receive motion down event.
1545 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1546
1547 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1548 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001549 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001550 mDispatcher->notifyDeviceReset(&args);
1551 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1552 0 /*expectedFlags*/);
1553}
1554
Svet Ganov5d3bc372020-01-26 23:11:07 -08001555TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001556 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001557
1558 // Create a couple of windows
1559 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1560 "First Window", ADISPLAY_ID_DEFAULT);
1561 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1562 "Second Window", ADISPLAY_ID_DEFAULT);
1563
1564 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001566
1567 // Send down to the first window
1568 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1569 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1570 mDispatcher->notifyMotion(&downMotionArgs);
1571 // Only the first window should get the down event
1572 firstWindow->consumeMotionDown();
1573 secondWindow->assertNoEvents();
1574
1575 // Transfer touch focus to the second window
1576 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1577 // The first window gets cancel and the second gets down
1578 firstWindow->consumeMotionCancel();
1579 secondWindow->consumeMotionDown();
1580
1581 // Send up event to the second window
1582 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1583 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1584 mDispatcher->notifyMotion(&upMotionArgs);
1585 // The first window gets no events and the second gets up
1586 firstWindow->assertNoEvents();
1587 secondWindow->consumeMotionUp();
1588}
1589
1590TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001591 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001592
1593 PointF touchPoint = {10, 10};
1594
1595 // Create a couple of windows
1596 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1597 "First Window", ADISPLAY_ID_DEFAULT);
1598 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1599 "Second Window", ADISPLAY_ID_DEFAULT);
1600
1601 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001602 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001603
1604 // Send down to the first window
1605 NotifyMotionArgs downMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1606 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint});
1607 mDispatcher->notifyMotion(&downMotionArgs);
1608 // Only the first window should get the down event
1609 firstWindow->consumeMotionDown();
1610 secondWindow->assertNoEvents();
1611
1612 // Send pointer down to the first window
1613 NotifyMotionArgs pointerDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1614 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1615 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1616 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1617 // Only the first window should get the pointer down event
1618 firstWindow->consumeMotionPointerDown(1);
1619 secondWindow->assertNoEvents();
1620
1621 // Transfer touch focus to the second window
1622 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1623 // The first window gets cancel and the second gets down and pointer down
1624 firstWindow->consumeMotionCancel();
1625 secondWindow->consumeMotionDown();
1626 secondWindow->consumeMotionPointerDown(1);
1627
1628 // Send pointer up to the second window
1629 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1630 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1631 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint});
1632 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1633 // The first window gets nothing and the second gets pointer up
1634 firstWindow->assertNoEvents();
1635 secondWindow->consumeMotionPointerUp(1);
1636
1637 // Send up event to the second window
1638 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1639 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1640 mDispatcher->notifyMotion(&upMotionArgs);
1641 // The first window gets nothing and the second gets up
1642 firstWindow->assertNoEvents();
1643 secondWindow->consumeMotionUp();
1644}
1645
1646TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001648
1649 // Create a non touch modal window that supports split touch
1650 sp<FakeWindowHandle> firstWindow = new FakeWindowHandle(application, mDispatcher,
1651 "First Window", ADISPLAY_ID_DEFAULT);
1652 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001653 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1654 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001655
1656 // Create a non touch modal window that supports split touch
1657 sp<FakeWindowHandle> secondWindow = new FakeWindowHandle(application, mDispatcher,
1658 "Second Window", ADISPLAY_ID_DEFAULT);
1659 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001660 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1661 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001662
1663 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001664 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001665
1666 PointF pointInFirst = {300, 200};
1667 PointF pointInSecond = {300, 600};
1668
1669 // Send down to the first window
1670 NotifyMotionArgs firstDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
1671 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst});
1672 mDispatcher->notifyMotion(&firstDownMotionArgs);
1673 // Only the first window should get the down event
1674 firstWindow->consumeMotionDown();
1675 secondWindow->assertNoEvents();
1676
1677 // Send down to the second window
1678 NotifyMotionArgs secondDownMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN
1679 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1680 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1681 mDispatcher->notifyMotion(&secondDownMotionArgs);
1682 // The first window gets a move and the second a down
1683 firstWindow->consumeMotionMove();
1684 secondWindow->consumeMotionDown();
1685
1686 // Transfer touch focus to the second window
1687 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1688 // The first window gets cancel and the new gets pointer down (it already saw down)
1689 firstWindow->consumeMotionCancel();
1690 secondWindow->consumeMotionPointerDown(1);
1691
1692 // Send pointer up to the second window
1693 NotifyMotionArgs pointerUpMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP
1694 | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1695 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInFirst, pointInSecond});
1696 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1697 // The first window gets nothing and the second gets pointer up
1698 firstWindow->assertNoEvents();
1699 secondWindow->consumeMotionPointerUp(1);
1700
1701 // Send up event to the second window
1702 NotifyMotionArgs upMotionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP,
1703 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT);
1704 mDispatcher->notifyMotion(&upMotionArgs);
1705 // The first window gets nothing and the second gets up
1706 firstWindow->assertNoEvents();
1707 secondWindow->consumeMotionUp();
1708}
1709
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001710TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001712 sp<FakeWindowHandle> window =
1713 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1714
Vishnu Nair47074b82020-08-14 11:54:47 -07001715 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001717 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001718
1719 window->consumeFocusEvent(true);
1720
1721 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1722 mDispatcher->notifyKey(&keyArgs);
1723
1724 // Window should receive key down event.
1725 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1726}
1727
1728TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001730 sp<FakeWindowHandle> window =
1731 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1732
Arthur Hung72d8dc32020-03-28 00:48:39 +00001733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001734
1735 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1736 mDispatcher->notifyKey(&keyArgs);
1737 mDispatcher->waitForIdle();
1738
1739 window->assertNoEvents();
1740}
1741
1742// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1743TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07001744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001745 sp<FakeWindowHandle> window =
1746 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1747
Arthur Hung72d8dc32020-03-28 00:48:39 +00001748 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001749
1750 // Send key
1751 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1752 mDispatcher->notifyKey(&keyArgs);
1753 // Send motion
1754 NotifyMotionArgs motionArgs =
1755 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1756 ADISPLAY_ID_DEFAULT);
1757 mDispatcher->notifyMotion(&motionArgs);
1758
1759 // Window should receive only the motion event
1760 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1761 window->assertNoEvents(); // Key event or focus event will not be received
1762}
1763
chaviwd1c23182019-12-20 18:44:56 -08001764class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001765public:
1766 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001767 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07001768 base::Result<std::unique_ptr<InputChannel>> channel =
1769 dispatcher->createInputMonitor(displayId, isGestureMonitor, name);
1770 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00001771 }
1772
chaviwd1c23182019-12-20 18:44:56 -08001773 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1774
1775 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1776 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1777 expectedDisplayId, expectedFlags);
1778 }
1779
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001780 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1781
1782 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1783
chaviwd1c23182019-12-20 18:44:56 -08001784 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1785 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1786 expectedDisplayId, expectedFlags);
1787 }
1788
1789 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1790 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1791 expectedDisplayId, expectedFlags);
1792 }
1793
1794 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1795
1796private:
1797 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001798};
1799
1800// Tests for gesture monitors
1801TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001802 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001803 sp<FakeWindowHandle> window =
1804 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001805 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001806
chaviwd1c23182019-12-20 18:44:56 -08001807 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1808 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001809
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001811 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001812 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001813 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001814 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001815}
1816
1817TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001819 sp<FakeWindowHandle> window =
1820 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1821
1822 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001823 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001824
Arthur Hung72d8dc32020-03-28 00:48:39 +00001825 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001826 setFocusedWindow(window);
1827
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001828 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001829
chaviwd1c23182019-12-20 18:44:56 -08001830 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1831 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001832
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1834 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001835 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001836 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001837}
1838
1839TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001841 sp<FakeWindowHandle> window =
1842 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001843 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001844
chaviwd1c23182019-12-20 18:44:56 -08001845 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1846 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001847
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001849 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001851 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001852 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001853
1854 window->releaseChannel();
1855
chaviwd1c23182019-12-20 18:44:56 -08001856 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001857
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001859 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001860 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001861 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001862}
1863
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001864TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1865 FakeMonitorReceiver monitor =
1866 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1867 true /*isGestureMonitor*/);
1868
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001870 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1871 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1872 ASSERT_TRUE(consumeSeq);
1873
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001874 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(DISPATCHING_TIMEOUT,
1875 monitor.getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001876 monitor.finishEvent(*consumeSeq);
1877 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001878 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(monitor.getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001879}
1880
chaviw81e2bb92019-12-18 15:03:51 -08001881TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08001883 sp<FakeWindowHandle> window =
1884 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1885
Arthur Hung72d8dc32020-03-28 00:48:39 +00001886 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001887
1888 NotifyMotionArgs motionArgs =
1889 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1890 ADISPLAY_ID_DEFAULT);
1891
1892 mDispatcher->notifyMotion(&motionArgs);
1893 // Window should receive motion down event.
1894 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1895
1896 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001897 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001898 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1899 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1900 motionArgs.pointerCoords[0].getX() - 10);
1901
1902 mDispatcher->notifyMotion(&motionArgs);
1903 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1904 0 /*expectedFlags*/);
1905}
1906
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001907/**
1908 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1909 * the device default right away. In the test scenario, we check both the default value,
1910 * and the action of enabling / disabling.
1911 */
1912TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07001913 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001914 sp<FakeWindowHandle> window =
1915 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1916
1917 // Set focused application.
1918 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001919 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001920
1921 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001922 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001923 setFocusedWindow(window);
1924
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001925 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1926
1927 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07001928 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001930 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1931
1932 SCOPED_TRACE("Disable touch mode");
1933 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07001934 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001935 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001936 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001937 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1938
1939 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07001940 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001942 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1943
1944 SCOPED_TRACE("Enable touch mode again");
1945 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07001946 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001947 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001948 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001949 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1950
1951 window->assertNoEvents();
1952}
1953
Gang Wange9087892020-01-07 12:17:14 -05001954TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05001956 sp<FakeWindowHandle> window =
1957 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1958
1959 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001960 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05001961
Arthur Hung72d8dc32020-03-28 00:48:39 +00001962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001963 setFocusedWindow(window);
1964
Gang Wange9087892020-01-07 12:17:14 -05001965 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1966
1967 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1968 mDispatcher->notifyKey(&keyArgs);
1969
1970 InputEvent* event = window->consume();
1971 ASSERT_NE(event, nullptr);
1972
1973 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1974 ASSERT_NE(verified, nullptr);
1975 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1976
1977 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1978 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1979 ASSERT_EQ(keyArgs.source, verified->source);
1980 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1981
1982 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1983
1984 ASSERT_EQ(keyArgs.action, verifiedKey.action);
1985 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05001986 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
1987 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
1988 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
1989 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
1990 ASSERT_EQ(0, verifiedKey.repeatCount);
1991}
1992
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001993TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001994 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08001995 sp<FakeWindowHandle> window =
1996 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1997
1998 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1999
Arthur Hung72d8dc32020-03-28 00:48:39 +00002000 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002001
2002 NotifyMotionArgs motionArgs =
2003 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2004 ADISPLAY_ID_DEFAULT);
2005 mDispatcher->notifyMotion(&motionArgs);
2006
2007 InputEvent* event = window->consume();
2008 ASSERT_NE(event, nullptr);
2009
2010 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2011 ASSERT_NE(verified, nullptr);
2012 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2013
2014 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2015 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2016 EXPECT_EQ(motionArgs.source, verified->source);
2017 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2018
2019 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2020
2021 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2022 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2023 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2024 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2025 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2026 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2027 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2028}
2029
chaviw09c8d2d2020-08-24 15:48:26 -07002030/**
2031 * Ensure that separate calls to sign the same data are generating the same key.
2032 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2033 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2034 * tests.
2035 */
2036TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2037 KeyEvent event = getTestKeyEvent();
2038 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2039
2040 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2041 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2042 ASSERT_EQ(hmac1, hmac2);
2043}
2044
2045/**
2046 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2047 */
2048TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2049 KeyEvent event = getTestKeyEvent();
2050 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2051 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2052
2053 verifiedEvent.deviceId += 1;
2054 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2055
2056 verifiedEvent.source += 1;
2057 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2058
2059 verifiedEvent.eventTimeNanos += 1;
2060 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2061
2062 verifiedEvent.displayId += 1;
2063 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2064
2065 verifiedEvent.action += 1;
2066 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2067
2068 verifiedEvent.downTimeNanos += 1;
2069 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2070
2071 verifiedEvent.flags += 1;
2072 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2073
2074 verifiedEvent.keyCode += 1;
2075 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2076
2077 verifiedEvent.scanCode += 1;
2078 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2079
2080 verifiedEvent.metaState += 1;
2081 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2082
2083 verifiedEvent.repeatCount += 1;
2084 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2085}
2086
Vishnu Nair958da932020-08-21 17:12:37 -07002087TEST_F(InputDispatcherTest, SetFocusedWindow) {
2088 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2089 sp<FakeWindowHandle> windowTop =
2090 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2091 sp<FakeWindowHandle> windowSecond =
2092 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2093 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2094
2095 // Top window is also focusable but is not granted focus.
2096 windowTop->setFocusable(true);
2097 windowSecond->setFocusable(true);
2098 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2099 setFocusedWindow(windowSecond);
2100
2101 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2103 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002104
2105 // Focused window should receive event.
2106 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2107 windowTop->assertNoEvents();
2108}
2109
2110TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2111 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2112 sp<FakeWindowHandle> window =
2113 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2114 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2115
2116 window->setFocusable(true);
2117 // Release channel for window is no longer valid.
2118 window->releaseChannel();
2119 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2120 setFocusedWindow(window);
2121
2122 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002123 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2124 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002125
2126 // window channel is invalid, so it should not receive any input event.
2127 window->assertNoEvents();
2128}
2129
2130TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2131 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2132 sp<FakeWindowHandle> window =
2133 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2134 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2135
2136 // Window is not focusable.
2137 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2138 setFocusedWindow(window);
2139
2140 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002141 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2142 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002143
2144 // window is invalid, so it should not receive any input event.
2145 window->assertNoEvents();
2146}
2147
2148TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
2149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2150 sp<FakeWindowHandle> windowTop =
2151 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2152 sp<FakeWindowHandle> windowSecond =
2153 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2154 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2155
2156 windowTop->setFocusable(true);
2157 windowSecond->setFocusable(true);
2158 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2159 setFocusedWindow(windowTop);
2160 windowTop->consumeFocusEvent(true);
2161
2162 setFocusedWindow(windowSecond, windowTop);
2163 windowSecond->consumeFocusEvent(true);
2164 windowTop->consumeFocusEvent(false);
2165
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2167 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002168
2169 // Focused window should receive event.
2170 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2171}
2172
2173TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
2174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2175 sp<FakeWindowHandle> windowTop =
2176 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2177 sp<FakeWindowHandle> windowSecond =
2178 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2179 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2180
2181 windowTop->setFocusable(true);
2182 windowSecond->setFocusable(true);
2183 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2184 setFocusedWindow(windowSecond, windowTop);
2185
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002186 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2187 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002188
2189 // Event should be dropped.
2190 windowTop->assertNoEvents();
2191 windowSecond->assertNoEvents();
2192}
2193
2194TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
2195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2196 sp<FakeWindowHandle> window =
2197 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2198 sp<FakeWindowHandle> previousFocusedWindow =
2199 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
2200 ADISPLAY_ID_DEFAULT);
2201 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2202
2203 window->setFocusable(true);
2204 previousFocusedWindow->setFocusable(true);
2205 window->setVisible(false);
2206 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
2207 setFocusedWindow(previousFocusedWindow);
2208 previousFocusedWindow->consumeFocusEvent(true);
2209
2210 // Requesting focus on invisible window takes focus from currently focused window.
2211 setFocusedWindow(window);
2212 previousFocusedWindow->consumeFocusEvent(false);
2213
2214 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07002216 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002217 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07002218
2219 // Window does not get focus event or key down.
2220 window->assertNoEvents();
2221
2222 // Window becomes visible.
2223 window->setVisible(true);
2224 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2225
2226 // Window receives focus event.
2227 window->consumeFocusEvent(true);
2228 // Focused window receives key down.
2229 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2230}
2231
Garfield Tan1c7bc862020-01-28 13:24:04 -08002232class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2233protected:
2234 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2235 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2236
Chris Yea209fde2020-07-22 13:54:51 -07002237 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002238 sp<FakeWindowHandle> mWindow;
2239
2240 virtual void SetUp() override {
2241 mFakePolicy = new FakeInputDispatcherPolicy();
2242 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2243 mDispatcher = new InputDispatcher(mFakePolicy);
2244 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2245 ASSERT_EQ(OK, mDispatcher->start());
2246
2247 setUpWindow();
2248 }
2249
2250 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07002251 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08002252 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2253
Vishnu Nair47074b82020-08-14 11:54:47 -07002254 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002255 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002256 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002257 mWindow->consumeFocusEvent(true);
2258 }
2259
Chris Ye2ad95392020-09-01 13:44:44 -07002260 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002261 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002262 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002263 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2264 mDispatcher->notifyKey(&keyArgs);
2265
2266 // Window should receive key down event.
2267 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2268 }
2269
2270 void expectKeyRepeatOnce(int32_t repeatCount) {
2271 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2272 InputEvent* repeatEvent = mWindow->consume();
2273 ASSERT_NE(nullptr, repeatEvent);
2274
2275 uint32_t eventType = repeatEvent->getType();
2276 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2277
2278 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2279 uint32_t eventAction = repeatKeyEvent->getAction();
2280 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2281 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2282 }
2283
Chris Ye2ad95392020-09-01 13:44:44 -07002284 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002285 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002286 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002287 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2288 mDispatcher->notifyKey(&keyArgs);
2289
2290 // Window should receive key down event.
2291 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2292 0 /*expectedFlags*/);
2293 }
2294};
2295
2296TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07002297 sendAndConsumeKeyDown(1 /* deviceId */);
2298 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2299 expectKeyRepeatOnce(repeatCount);
2300 }
2301}
2302
2303TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
2304 sendAndConsumeKeyDown(1 /* deviceId */);
2305 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2306 expectKeyRepeatOnce(repeatCount);
2307 }
2308 sendAndConsumeKeyDown(2 /* deviceId */);
2309 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08002310 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2311 expectKeyRepeatOnce(repeatCount);
2312 }
2313}
2314
2315TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07002316 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002317 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07002318 sendAndConsumeKeyUp(1 /* deviceId */);
2319 mWindow->assertNoEvents();
2320}
2321
2322TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
2323 sendAndConsumeKeyDown(1 /* deviceId */);
2324 expectKeyRepeatOnce(1 /*repeatCount*/);
2325 sendAndConsumeKeyDown(2 /* deviceId */);
2326 expectKeyRepeatOnce(1 /*repeatCount*/);
2327 // Stale key up from device 1.
2328 sendAndConsumeKeyUp(1 /* deviceId */);
2329 // Device 2 is still down, keep repeating
2330 expectKeyRepeatOnce(2 /*repeatCount*/);
2331 expectKeyRepeatOnce(3 /*repeatCount*/);
2332 // Device 2 key up
2333 sendAndConsumeKeyUp(2 /* deviceId */);
2334 mWindow->assertNoEvents();
2335}
2336
2337TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
2338 sendAndConsumeKeyDown(1 /* deviceId */);
2339 expectKeyRepeatOnce(1 /*repeatCount*/);
2340 sendAndConsumeKeyDown(2 /* deviceId */);
2341 expectKeyRepeatOnce(1 /*repeatCount*/);
2342 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
2343 sendAndConsumeKeyUp(2 /* deviceId */);
2344 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08002345 mWindow->assertNoEvents();
2346}
2347
2348TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07002349 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002350 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2351 InputEvent* repeatEvent = mWindow->consume();
2352 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2353 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2354 IdGenerator::getSource(repeatEvent->getId()));
2355 }
2356}
2357
2358TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07002359 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002360
2361 std::unordered_set<int32_t> idSet;
2362 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2363 InputEvent* repeatEvent = mWindow->consume();
2364 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2365 int32_t id = repeatEvent->getId();
2366 EXPECT_EQ(idSet.end(), idSet.find(id));
2367 idSet.insert(id);
2368 }
2369}
2370
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002371/* Test InputDispatcher for MultiDisplay */
2372class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2373public:
2374 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002375 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002376 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002377
Chris Yea209fde2020-07-22 13:54:51 -07002378 application1 = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002379 windowInPrimary = new FakeWindowHandle(application1, mDispatcher, "D_1",
2380 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002381
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002382 // Set focus window for primary display, but focused display would be second one.
2383 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07002384 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002385 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002386 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002387 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002388
Chris Yea209fde2020-07-22 13:54:51 -07002389 application2 = std::make_shared<FakeApplicationHandle>();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002390 windowInSecondary = new FakeWindowHandle(application2, mDispatcher, "D_2",
2391 SECOND_DISPLAY_ID);
2392 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002393 // Set focus display to second one.
2394 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2395 // Set focus window for second display.
2396 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07002397 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002398 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002399 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002400 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002401 }
2402
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002403 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002404 InputDispatcherTest::TearDown();
2405
Chris Yea209fde2020-07-22 13:54:51 -07002406 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002407 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07002408 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002409 windowInSecondary.clear();
2410 }
2411
2412protected:
Chris Yea209fde2020-07-22 13:54:51 -07002413 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002414 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07002415 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002416 sp<FakeWindowHandle> windowInSecondary;
2417};
2418
2419TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2420 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2422 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2423 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002424 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002425 windowInSecondary->assertNoEvents();
2426
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002427 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2429 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002431 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002432 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002433}
2434
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002435TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002436 // Test inject a key down with display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2438 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002439 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002440 windowInSecondary->assertNoEvents();
2441
2442 // Test inject a key down without display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2444 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002445 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002446 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002447
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002448 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002449 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002450
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002451 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002452 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2453 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002454
2455 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002456 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2457 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08002458 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002459 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002460 windowInSecondary->assertNoEvents();
2461}
2462
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002463// Test per-display input monitors for motion event.
2464TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002465 FakeMonitorReceiver monitorInPrimary =
2466 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2467 FakeMonitorReceiver monitorInSecondary =
2468 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002469
2470 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2472 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2473 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002474 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002475 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002476 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002477 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002478
2479 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2481 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002483 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002484 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002485 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002486 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002487
2488 // Test inject a non-pointer motion event.
2489 // If specific a display, it will dispatch to the focused window of particular display,
2490 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2492 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2493 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002494 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002495 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002496 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002497 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002498}
2499
2500// Test per-display input monitors for key event.
2501TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
2502 //Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002503 FakeMonitorReceiver monitorInPrimary =
2504 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2505 FakeMonitorReceiver monitorInSecondary =
2506 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002507
2508 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2510 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002511 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002512 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002513 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002514 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002515}
2516
Vishnu Nair958da932020-08-21 17:12:37 -07002517TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
2518 sp<FakeWindowHandle> secondWindowInPrimary =
2519 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2520 secondWindowInPrimary->setFocusable(true);
2521 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
2522 setFocusedWindow(secondWindowInPrimary);
2523 windowInPrimary->consumeFocusEvent(false);
2524 secondWindowInPrimary->consumeFocusEvent(true);
2525
2526 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2528 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002529 windowInPrimary->assertNoEvents();
2530 windowInSecondary->assertNoEvents();
2531 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2532}
2533
Jackal Guof9696682018-10-05 12:23:23 +08002534class InputFilterTest : public InputDispatcherTest {
2535protected:
2536 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2537
2538 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2539 NotifyMotionArgs motionArgs;
2540
2541 motionArgs = generateMotionArgs(
2542 AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2543 mDispatcher->notifyMotion(&motionArgs);
2544 motionArgs = generateMotionArgs(
2545 AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
2546 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002547 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002548 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002549 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002550 } else {
2551 mFakePolicy->assertFilterInputEventWasNotCalled();
2552 }
2553 }
2554
2555 void testNotifyKey(bool expectToBeFiltered) {
2556 NotifyKeyArgs keyArgs;
2557
2558 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2559 mDispatcher->notifyKey(&keyArgs);
2560 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2561 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002562 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002563
2564 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002565 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002566 } else {
2567 mFakePolicy->assertFilterInputEventWasNotCalled();
2568 }
2569 }
2570};
2571
2572// Test InputFilter for MotionEvent
2573TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2574 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2575 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2576 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2577
2578 // Enable InputFilter
2579 mDispatcher->setInputFilterEnabled(true);
2580 // Test touch on both primary and second display, and check if both events are filtered.
2581 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2582 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2583
2584 // Disable InputFilter
2585 mDispatcher->setInputFilterEnabled(false);
2586 // Test touch on both primary and second display, and check if both events aren't filtered.
2587 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2588 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2589}
2590
2591// Test InputFilter for KeyEvent
2592TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2593 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2594 testNotifyKey(/*expectToBeFiltered*/ false);
2595
2596 // Enable InputFilter
2597 mDispatcher->setInputFilterEnabled(true);
2598 // Send a key event, and check if it is filtered.
2599 testNotifyKey(/*expectToBeFiltered*/ true);
2600
2601 // Disable InputFilter
2602 mDispatcher->setInputFilterEnabled(false);
2603 // Send a key event, and check if it isn't filtered.
2604 testNotifyKey(/*expectToBeFiltered*/ false);
2605}
2606
chaviwfd6d3512019-03-25 13:23:49 -07002607class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002608 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002609 InputDispatcherTest::SetUp();
2610
Chris Yea209fde2020-07-22 13:54:51 -07002611 std::shared_ptr<FakeApplicationHandle> application =
2612 std::make_shared<FakeApplicationHandle>();
chaviwfd6d3512019-03-25 13:23:49 -07002613 mUnfocusedWindow = new FakeWindowHandle(application, mDispatcher, "Top",
2614 ADISPLAY_ID_DEFAULT);
2615 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2616 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2617 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002618 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002619
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002620 mFocusedWindow =
2621 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2622 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002623 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002624
2625 // Set focused application.
2626 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002627 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07002628
2629 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002630 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002631 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002632 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002633 }
2634
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002635 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002636 InputDispatcherTest::TearDown();
2637
2638 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002639 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002640 }
2641
2642protected:
2643 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002644 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002645 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002646};
2647
2648// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2649// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2650// the onPointerDownOutsideFocus callback.
2651TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002653 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2654 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002656 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002657
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002658 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002659 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2660}
2661
2662// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2663// DOWN on the window that doesn't have focus. Ensure no window received the
2664// onPointerDownOutsideFocus callback.
2665TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002667 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002669 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002670
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002671 ASSERT_TRUE(mDispatcher->waitForIdle());
2672 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002673}
2674
2675// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2676// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2677TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2679 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002680 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002681
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002682 ASSERT_TRUE(mDispatcher->waitForIdle());
2683 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002684}
2685
2686// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2687// DOWN on the window that already has focus. Ensure no window received the
2688// onPointerDownOutsideFocus callback.
2689TEST_F(InputDispatcherOnPointerDownOutsideFocus,
2690 OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002692 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002693 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002695 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002696
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002697 ASSERT_TRUE(mDispatcher->waitForIdle());
2698 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002699}
2700
chaviwaf87b3e2019-10-01 16:59:28 -07002701// These tests ensures we can send touch events to a single client when there are multiple input
2702// windows that point to the same client token.
2703class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2704 virtual void SetUp() override {
2705 InputDispatcherTest::SetUp();
2706
Chris Yea209fde2020-07-22 13:54:51 -07002707 std::shared_ptr<FakeApplicationHandle> application =
2708 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07002709 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2710 ADISPLAY_ID_DEFAULT);
2711 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2712 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
Michael Wright44753b12020-07-08 13:48:11 +01002713 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2714 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002715 mWindow1->setFrame(Rect(0, 0, 100, 100));
2716
2717 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2718 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002719 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2720 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002721 mWindow2->setFrame(Rect(100, 100, 200, 200));
2722
Arthur Hung72d8dc32020-03-28 00:48:39 +00002723 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002724 }
2725
2726protected:
2727 sp<FakeWindowHandle> mWindow1;
2728 sp<FakeWindowHandle> mWindow2;
2729
2730 // Helper function to convert the point from screen coordinates into the window's space
2731 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07002732 vec2 vals = windowInfo->transform.transform(point.x, point.y);
2733 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07002734 }
2735
2736 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2737 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002738 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002739 InputEvent* event = window->consume();
2740
2741 ASSERT_NE(nullptr, event) << name.c_str()
2742 << ": consumer should have returned non-NULL event.";
2743
2744 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2745 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2746 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2747
2748 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2749 EXPECT_EQ(expectedAction, motionEvent.getAction());
2750
2751 for (size_t i = 0; i < points.size(); i++) {
2752 float expectedX = points[i].x;
2753 float expectedY = points[i].y;
2754
2755 EXPECT_EQ(expectedX, motionEvent.getX(i))
2756 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2757 << ", got " << motionEvent.getX(i);
2758 EXPECT_EQ(expectedY, motionEvent.getY(i))
2759 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2760 << ", got " << motionEvent.getY(i);
2761 }
2762 }
chaviw9eaa22c2020-07-01 16:21:27 -07002763
2764 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
2765 std::vector<PointF> expectedPoints) {
2766 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
2767 ADISPLAY_ID_DEFAULT, touchedPoints);
2768 mDispatcher->notifyMotion(&motionArgs);
2769
2770 // Always consume from window1 since it's the window that has the InputReceiver
2771 consumeMotionEvent(mWindow1, action, expectedPoints);
2772 }
chaviwaf87b3e2019-10-01 16:59:28 -07002773};
2774
2775TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2776 // Touch Window 1
2777 PointF touchedPoint = {10, 10};
2778 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002779 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002780
2781 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002782 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002783
2784 // Touch Window 2
2785 touchedPoint = {150, 150};
2786 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002787 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002788}
2789
chaviw9eaa22c2020-07-01 16:21:27 -07002790TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
2791 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07002792 mWindow2->setWindowScale(0.5f, 0.5f);
2793
2794 // Touch Window 1
2795 PointF touchedPoint = {10, 10};
2796 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002797 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002798 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002799 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002800
2801 // Touch Window 2
2802 touchedPoint = {150, 150};
2803 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002804 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
2805 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002806
chaviw9eaa22c2020-07-01 16:21:27 -07002807 // Update the transform so rotation is set
2808 mWindow2->setWindowTransform(0, -1, 1, 0);
2809 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2810 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002811}
2812
chaviw9eaa22c2020-07-01 16:21:27 -07002813TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002814 mWindow2->setWindowScale(0.5f, 0.5f);
2815
2816 // Touch Window 1
2817 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2818 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002819 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002820
2821 // Touch Window 2
2822 int32_t actionPointerDown =
2823 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002824 touchedPoints.push_back(PointF{150, 150});
2825 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2826 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002827
chaviw9eaa22c2020-07-01 16:21:27 -07002828 // Release Window 2
2829 int32_t actionPointerUp =
2830 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2831 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2832 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002833
chaviw9eaa22c2020-07-01 16:21:27 -07002834 // Update the transform so rotation is set for Window 2
2835 mWindow2->setWindowTransform(0, -1, 1, 0);
2836 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2837 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002838}
2839
chaviw9eaa22c2020-07-01 16:21:27 -07002840TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002841 mWindow2->setWindowScale(0.5f, 0.5f);
2842
2843 // Touch Window 1
2844 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2845 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002846 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002847
2848 // Touch Window 2
2849 int32_t actionPointerDown =
2850 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002851 touchedPoints.push_back(PointF{150, 150});
2852 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002853
chaviw9eaa22c2020-07-01 16:21:27 -07002854 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002855
2856 // Move both windows
2857 touchedPoints = {{20, 20}, {175, 175}};
2858 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2859 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2860
chaviw9eaa22c2020-07-01 16:21:27 -07002861 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002862
chaviw9eaa22c2020-07-01 16:21:27 -07002863 // Release Window 2
2864 int32_t actionPointerUp =
2865 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2866 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2867 expectedPoints.pop_back();
2868
2869 // Touch Window 2
2870 mWindow2->setWindowTransform(0, -1, 1, 0);
2871 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2872 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
2873
2874 // Move both windows
2875 touchedPoints = {{20, 20}, {175, 175}};
2876 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2877 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2878
2879 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002880}
2881
2882TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2883 mWindow1->setWindowScale(0.5f, 0.5f);
2884
2885 // Touch Window 1
2886 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2887 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002888 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002889
2890 // Touch Window 2
2891 int32_t actionPointerDown =
2892 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002893 touchedPoints.push_back(PointF{150, 150});
2894 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002895
chaviw9eaa22c2020-07-01 16:21:27 -07002896 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002897
2898 // Move both windows
2899 touchedPoints = {{20, 20}, {175, 175}};
2900 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2901 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2902
chaviw9eaa22c2020-07-01 16:21:27 -07002903 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002904}
2905
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002906class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2907 virtual void SetUp() override {
2908 InputDispatcherTest::SetUp();
2909
Chris Yea209fde2020-07-22 13:54:51 -07002910 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002911 mApplication->setDispatchingTimeout(20ms);
2912 mWindow =
2913 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2914 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002915 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07002916 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002917 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2918 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002919 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002920
2921 // Set focused application.
2922 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
2923
2924 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002925 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002926 mWindow->consumeFocusEvent(true);
2927 }
2928
2929 virtual void TearDown() override {
2930 InputDispatcherTest::TearDown();
2931 mWindow.clear();
2932 }
2933
2934protected:
Chris Yea209fde2020-07-22 13:54:51 -07002935 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002936 sp<FakeWindowHandle> mWindow;
2937 static constexpr PointF WINDOW_LOCATION = {20, 20};
2938
2939 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002941 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2942 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002944 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2945 WINDOW_LOCATION));
2946 }
2947};
2948
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002949// Send a tap and respond, which should not cause an ANR.
2950TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
2951 tapOnWindow();
2952 mWindow->consumeMotionDown();
2953 mWindow->consumeMotionUp();
2954 ASSERT_TRUE(mDispatcher->waitForIdle());
2955 mFakePolicy->assertNotifyAnrWasNotCalled();
2956}
2957
2958// Send a regular key and respond, which should not cause an ANR.
2959TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002961 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
2962 ASSERT_TRUE(mDispatcher->waitForIdle());
2963 mFakePolicy->assertNotifyAnrWasNotCalled();
2964}
2965
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002966TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
2967 mWindow->setFocusable(false);
2968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
2969 mWindow->consumeFocusEvent(false);
2970
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002971 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002972 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002973 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
2974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05002975 // Key will not go to window because we have no focused window.
2976 // The 'no focused window' ANR timer should start instead.
2977
2978 // Now, the focused application goes away.
2979 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
2980 // The key should get dropped and there should be no ANR.
2981
2982 ASSERT_TRUE(mDispatcher->waitForIdle());
2983 mFakePolicy->assertNotifyAnrWasNotCalled();
2984}
2985
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002986// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002987// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
2988// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002989TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002991 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2992 WINDOW_LOCATION));
2993
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002994 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
2995 ASSERT_TRUE(sequenceNum);
2996 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05002997 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002998
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002999 mWindow->finishEvent(*sequenceNum);
3000 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3001 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003002 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003003 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003004}
3005
3006// Send a key to the app and have the app not respond right away.
3007TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
3008 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003010 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
3011 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003012 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003013 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003014 ASSERT_TRUE(mDispatcher->waitForIdle());
3015}
3016
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003017// We have a focused application, but no focused window
3018TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003019 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003020 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3021 mWindow->consumeFocusEvent(false);
3022
3023 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003025 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3026 WINDOW_LOCATION));
3027 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
3028 mDispatcher->waitForIdle();
3029 mFakePolicy->assertNotifyAnrWasNotCalled();
3030
3031 // Once a focused event arrives, we get an ANR for this application
3032 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3033 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003034 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003035 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003036 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3037 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003038 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003039 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003040 ASSERT_TRUE(mDispatcher->waitForIdle());
3041}
3042
3043// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003044// Make sure that we don't notify policy twice about the same ANR.
3045TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003046 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003047 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3048 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003049
3050 // Once a focused event arrives, we get an ANR for this application
3051 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3052 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003053 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003054 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003055 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3056 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003057 const std::chrono::duration appTimeout =
3058 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003059 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003060
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003061 std::this_thread::sleep_for(appTimeout);
3062 // ANR should not be raised again. It is up to policy to do that if it desires.
3063 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003064
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003065 // If we now get a focused window, the ANR should stop, but the policy handles that via
3066 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003067 ASSERT_TRUE(mDispatcher->waitForIdle());
3068}
3069
3070// We have a focused application, but no focused window
3071TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003072 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003073 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3074 mWindow->consumeFocusEvent(false);
3075
3076 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003077 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003078 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003079 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3080 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003081
3082 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003083 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003084
3085 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003086 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003087 ASSERT_TRUE(mDispatcher->waitForIdle());
3088 mWindow->assertNoEvents();
3089}
3090
3091/**
3092 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
3093 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
3094 * If we process 1 of the events, but ANR on the second event with the same timestamp,
3095 * the ANR mechanism should still work.
3096 *
3097 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
3098 * DOWN event, while not responding on the second one.
3099 */
3100TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
3101 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
3102 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3103 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3104 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3105 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003106 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003107
3108 // Now send ACTION_UP, with identical timestamp
3109 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3110 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3111 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3112 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003113 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003114
3115 // We have now sent down and up. Let's consume first event and then ANR on the second.
3116 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3117 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003118 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003119}
3120
3121// If an app is not responding to a key event, gesture monitors should continue to receive
3122// new motion events
3123TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
3124 FakeMonitorReceiver monitor =
3125 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3126 true /*isGestureMonitor*/);
3127
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3129 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003130 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003132
3133 // Stuck on the ACTION_UP
3134 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003135 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003136
3137 // New tap will go to the gesture monitor, but not to the window
3138 tapOnWindow();
3139 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3140 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3141
3142 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3143 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003144 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003145 mWindow->assertNoEvents();
3146 monitor.assertNoEvents();
3147}
3148
3149// If an app is not responding to a motion event, gesture monitors should continue to receive
3150// new motion events
3151TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
3152 FakeMonitorReceiver monitor =
3153 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3154 true /*isGestureMonitor*/);
3155
3156 tapOnWindow();
3157 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3158 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3159
3160 mWindow->consumeMotionDown();
3161 // Stuck on the ACTION_UP
3162 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003163 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003164
3165 // New tap will go to the gesture monitor, but not to the window
3166 tapOnWindow();
3167 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3168 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3169
3170 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3171 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003172 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003173 mWindow->assertNoEvents();
3174 monitor.assertNoEvents();
3175}
3176
3177// If a window is unresponsive, then you get anr. if the window later catches up and starts to
3178// process events, you don't get an anr. When the window later becomes unresponsive again, you
3179// get an ANR again.
3180// 1. tap -> block on ACTION_UP -> receive ANR
3181// 2. consume all pending events (= queue becomes healthy again)
3182// 3. tap again -> block on ACTION_UP again -> receive ANR second time
3183TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
3184 tapOnWindow();
3185
3186 mWindow->consumeMotionDown();
3187 // Block on ACTION_UP
3188 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003189 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003190 mWindow->consumeMotionUp(); // Now the connection should be healthy again
3191 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003192 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003193 mWindow->assertNoEvents();
3194
3195 tapOnWindow();
3196 mWindow->consumeMotionDown();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003197 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003198 mWindow->consumeMotionUp();
3199
3200 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003201 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
3202 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003203 mWindow->assertNoEvents();
3204}
3205
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003206// If a connection remains unresponsive for a while, make sure policy is only notified once about
3207// it.
3208TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003210 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3211 WINDOW_LOCATION));
3212
3213 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003214 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003215 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003216 // 'notifyConnectionUnresponsive' should only be called once per connection
3217 mFakePolicy->assertNotifyAnrWasNotCalled();
3218 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003219 mWindow->consumeMotionDown();
3220 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3221 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3222 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003223 mDispatcher->waitForIdle();
3224 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
3225 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003226}
3227
3228/**
3229 * If a window is processing a motion event, and then a key event comes in, the key event should
3230 * not to to the focused window until the motion is processed.
3231 *
3232 * Warning!!!
3233 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3234 * and the injection timeout that we specify when injecting the key.
3235 * We must have the injection timeout (10ms) be smaller than
3236 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3237 *
3238 * If that value changes, this test should also change.
3239 */
3240TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
3241 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3242 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3243
3244 tapOnWindow();
3245 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3246 ASSERT_TRUE(downSequenceNum);
3247 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3248 ASSERT_TRUE(upSequenceNum);
3249 // Don't finish the events yet, and send a key
3250 // Injection will "succeed" because we will eventually give up and send the key to the focused
3251 // window even if motions are still being processed. But because the injection timeout is short,
3252 // we will receive INJECTION_TIMED_OUT as the result.
3253
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003254 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003255 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003256 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3257 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003258 // Key will not be sent to the window, yet, because the window is still processing events
3259 // and the key remains pending, waiting for the touch events to be processed
3260 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3261 ASSERT_FALSE(keySequenceNum);
3262
3263 std::this_thread::sleep_for(500ms);
3264 // if we wait long enough though, dispatcher will give up, and still send the key
3265 // to the focused window, even though we have not yet finished the motion event
3266 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3267 mWindow->finishEvent(*downSequenceNum);
3268 mWindow->finishEvent(*upSequenceNum);
3269}
3270
3271/**
3272 * If a window is processing a motion event, and then a key event comes in, the key event should
3273 * not go to the focused window until the motion is processed.
3274 * If then a new motion comes in, then the pending key event should be going to the currently
3275 * focused window right away.
3276 */
3277TEST_F(InputDispatcherSingleWindowAnr,
3278 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
3279 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3280 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3281
3282 tapOnWindow();
3283 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3284 ASSERT_TRUE(downSequenceNum);
3285 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3286 ASSERT_TRUE(upSequenceNum);
3287 // Don't finish the events yet, and send a key
3288 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003290 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003291 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003292 // At this point, key is still pending, and should not be sent to the application yet.
3293 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3294 ASSERT_FALSE(keySequenceNum);
3295
3296 // Now tap down again. It should cause the pending key to go to the focused window right away.
3297 tapOnWindow();
3298 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3299 // the other events yet. We can finish events in any order.
3300 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3301 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3302 mWindow->consumeMotionDown();
3303 mWindow->consumeMotionUp();
3304 mWindow->assertNoEvents();
3305}
3306
3307class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3308 virtual void SetUp() override {
3309 InputDispatcherTest::SetUp();
3310
Chris Yea209fde2020-07-22 13:54:51 -07003311 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003312 mApplication->setDispatchingTimeout(10ms);
3313 mUnfocusedWindow =
3314 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3315 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3316 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3317 // window.
3318 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003319 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3320 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3321 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003322
3323 mFocusedWindow =
3324 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003325 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003326 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003327 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3328 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003329
3330 // Set focused application.
3331 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07003332 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003333
3334 // Expect one focus window exist in display.
3335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003336 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003337 mFocusedWindow->consumeFocusEvent(true);
3338 }
3339
3340 virtual void TearDown() override {
3341 InputDispatcherTest::TearDown();
3342
3343 mUnfocusedWindow.clear();
3344 mFocusedWindow.clear();
3345 }
3346
3347protected:
Chris Yea209fde2020-07-22 13:54:51 -07003348 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003349 sp<FakeWindowHandle> mUnfocusedWindow;
3350 sp<FakeWindowHandle> mFocusedWindow;
3351 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3352 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3353 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3354
3355 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3356
3357 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3358
3359private:
3360 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003362 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3363 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003365 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3366 location));
3367 }
3368};
3369
3370// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3371// should be ANR'd first.
3372TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003374 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3375 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003377 mFocusedWindow->consumeMotionDown();
3378 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3379 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3380 // We consumed all events, so no ANR
3381 ASSERT_TRUE(mDispatcher->waitForIdle());
3382 mFakePolicy->assertNotifyAnrWasNotCalled();
3383
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003385 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3386 FOCUSED_WINDOW_LOCATION));
3387 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3388 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003389
3390 const std::chrono::duration timeout =
3391 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003392 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
3393 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
3394 // sequence to make it consistent
3395 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003396 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003397 mFocusedWindow->consumeMotionDown();
3398 // This cancel is generated because the connection was unresponsive
3399 mFocusedWindow->consumeMotionCancel();
3400 mFocusedWindow->assertNoEvents();
3401 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003402 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003403 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
3404 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003405}
3406
3407// If we have 2 windows with identical timeouts that are both unresponsive,
3408// it doesn't matter which order they should have ANR.
3409// But we should receive ANR for both.
3410TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3411 // Set the timeout for unfocused window to match the focused window
3412 mUnfocusedWindow->setDispatchingTimeout(10ms);
3413 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3414
3415 tapOnFocusedWindow();
3416 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003417 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveConnectionToken(10ms);
3418 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveConnectionToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003419
3420 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003421 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
3422 mFocusedWindow->getToken() == anrConnectionToken2);
3423 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
3424 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003425
3426 ASSERT_TRUE(mDispatcher->waitForIdle());
3427 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003428
3429 mFocusedWindow->consumeMotionDown();
3430 mFocusedWindow->consumeMotionUp();
3431 mUnfocusedWindow->consumeMotionOutside();
3432
3433 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveConnectionToken();
3434 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveConnectionToken();
3435
3436 // Both applications should be marked as responsive, in any order
3437 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
3438 mFocusedWindow->getToken() == responsiveToken2);
3439 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
3440 mUnfocusedWindow->getToken() == responsiveToken2);
3441 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003442}
3443
3444// If a window is already not responding, the second tap on the same window should be ignored.
3445// We should also log an error to account for the dropped event (not tested here).
3446// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3447TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3448 tapOnFocusedWindow();
3449 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3450 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3451 // Receive the events, but don't respond
3452 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3453 ASSERT_TRUE(downEventSequenceNum);
3454 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3455 ASSERT_TRUE(upEventSequenceNum);
3456 const std::chrono::duration timeout =
3457 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003458 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003459
3460 // Tap once again
3461 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003462 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003463 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3464 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003465 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003466 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3467 FOCUSED_WINDOW_LOCATION));
3468 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3469 // valid touch target
3470 mUnfocusedWindow->assertNoEvents();
3471
3472 // Consume the first tap
3473 mFocusedWindow->finishEvent(*downEventSequenceNum);
3474 mFocusedWindow->finishEvent(*upEventSequenceNum);
3475 ASSERT_TRUE(mDispatcher->waitForIdle());
3476 // The second tap did not go to the focused window
3477 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003478 // Since all events are finished, connection should be deemed healthy again
3479 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003480 mFakePolicy->assertNotifyAnrWasNotCalled();
3481}
3482
3483// If you tap outside of all windows, there will not be ANR
3484TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003485 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003486 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3487 LOCATION_OUTSIDE_ALL_WINDOWS));
3488 ASSERT_TRUE(mDispatcher->waitForIdle());
3489 mFakePolicy->assertNotifyAnrWasNotCalled();
3490}
3491
3492// Since the focused window is paused, tapping on it should not produce any events
3493TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3494 mFocusedWindow->setPaused(true);
3495 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3496
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003497 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003498 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3499 FOCUSED_WINDOW_LOCATION));
3500
3501 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3502 ASSERT_TRUE(mDispatcher->waitForIdle());
3503 // Should not ANR because the window is paused, and touches shouldn't go to it
3504 mFakePolicy->assertNotifyAnrWasNotCalled();
3505
3506 mFocusedWindow->assertNoEvents();
3507 mUnfocusedWindow->assertNoEvents();
3508}
3509
3510/**
3511 * If a window is processing a motion event, and then a key event comes in, the key event should
3512 * not to to the focused window until the motion is processed.
3513 * If a different window becomes focused at this time, the key should go to that window instead.
3514 *
3515 * Warning!!!
3516 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3517 * and the injection timeout that we specify when injecting the key.
3518 * We must have the injection timeout (10ms) be smaller than
3519 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3520 *
3521 * If that value changes, this test should also change.
3522 */
3523TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3524 // Set a long ANR timeout to prevent it from triggering
3525 mFocusedWindow->setDispatchingTimeout(2s);
3526 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3527
3528 tapOnUnfocusedWindow();
3529 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3530 ASSERT_TRUE(downSequenceNum);
3531 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3532 ASSERT_TRUE(upSequenceNum);
3533 // Don't finish the events yet, and send a key
3534 // Injection will succeed because we will eventually give up and send the key to the focused
3535 // window even if motions are still being processed.
3536
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003537 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003538 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003539 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003541 // Key will not be sent to the window, yet, because the window is still processing events
3542 // and the key remains pending, waiting for the touch events to be processed
3543 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3544 ASSERT_FALSE(keySequenceNum);
3545
3546 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07003547 mFocusedWindow->setFocusable(false);
3548 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003549 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003550 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003551
3552 // Focus events should precede the key events
3553 mUnfocusedWindow->consumeFocusEvent(true);
3554 mFocusedWindow->consumeFocusEvent(false);
3555
3556 // Finish the tap events, which should unblock dispatcher
3557 mUnfocusedWindow->finishEvent(*downSequenceNum);
3558 mUnfocusedWindow->finishEvent(*upSequenceNum);
3559
3560 // Now that all queues are cleared and no backlog in the connections, the key event
3561 // can finally go to the newly focused "mUnfocusedWindow".
3562 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3563 mFocusedWindow->assertNoEvents();
3564 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003565 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003566}
3567
3568// When the touch stream is split across 2 windows, and one of them does not respond,
3569// then ANR should be raised and the touch should be canceled for the unresponsive window.
3570// The other window should not be affected by that.
3571TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3572 // Touch Window 1
3573 NotifyMotionArgs motionArgs =
3574 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3575 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3576 mDispatcher->notifyMotion(&motionArgs);
3577 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3578 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3579
3580 // Touch Window 2
3581 int32_t actionPointerDown =
3582 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3583
3584 motionArgs =
3585 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3586 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3587 mDispatcher->notifyMotion(&motionArgs);
3588
3589 const std::chrono::duration timeout =
3590 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003591 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003592
3593 mUnfocusedWindow->consumeMotionDown();
3594 mFocusedWindow->consumeMotionDown();
3595 // Focused window may or may not receive ACTION_MOVE
3596 // But it should definitely receive ACTION_CANCEL due to the ANR
3597 InputEvent* event;
3598 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3599 ASSERT_TRUE(moveOrCancelSequenceNum);
3600 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3601 ASSERT_NE(nullptr, event);
3602 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3603 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3604 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3605 mFocusedWindow->consumeMotionCancel();
3606 } else {
3607 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3608 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003609 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003610 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
3611
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003612 mUnfocusedWindow->assertNoEvents();
3613 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003614 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003615}
3616
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003617/**
3618 * If we have no focused window, and a key comes in, we start the ANR timer.
3619 * The focused application should add a focused window before the timer runs out to prevent ANR.
3620 *
3621 * If the user touches another application during this time, the key should be dropped.
3622 * Next, if a new focused window comes in, without toggling the focused application,
3623 * then no ANR should occur.
3624 *
3625 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
3626 * but in some cases the policy may not update the focused application.
3627 */
3628TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
3629 std::shared_ptr<FakeApplicationHandle> focusedApplication =
3630 std::make_shared<FakeApplicationHandle>();
3631 focusedApplication->setDispatchingTimeout(60ms);
3632 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
3633 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
3634 mFocusedWindow->setFocusable(false);
3635
3636 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3637 mFocusedWindow->consumeFocusEvent(false);
3638
3639 // Send a key. The ANR timer should start because there is no focused window.
3640 // 'focusedApplication' will get blamed if this timer completes.
3641 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003642 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003643 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003644 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003646
3647 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
3648 // then the injected touches won't cause the focused event to get dropped.
3649 // The dispatcher only checks for whether the queue should be pruned upon queueing.
3650 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
3651 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
3652 // For this test, it means that the key would get delivered to the window once it becomes
3653 // focused.
3654 std::this_thread::sleep_for(10ms);
3655
3656 // Touch unfocused window. This should force the pending key to get dropped.
3657 NotifyMotionArgs motionArgs =
3658 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3659 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
3660 mDispatcher->notifyMotion(&motionArgs);
3661
3662 // We do not consume the motion right away, because that would require dispatcher to first
3663 // process (== drop) the key event, and by that time, ANR will be raised.
3664 // Set the focused window first.
3665 mFocusedWindow->setFocusable(true);
3666 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3667 setFocusedWindow(mFocusedWindow);
3668 mFocusedWindow->consumeFocusEvent(true);
3669 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
3670 // to another application. This could be a bug / behaviour in the policy.
3671
3672 mUnfocusedWindow->consumeMotionDown();
3673
3674 ASSERT_TRUE(mDispatcher->waitForIdle());
3675 // Should not ANR because we actually have a focused window. It was just added too slowly.
3676 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
3677}
3678
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05003679// These tests ensure we cannot send touch events to a window that's positioned behind a window
3680// that has feature NO_INPUT_CHANNEL.
3681// Layout:
3682// Top (closest to user)
3683// mNoInputWindow (above all windows)
3684// mBottomWindow
3685// Bottom (furthest from user)
3686class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
3687 virtual void SetUp() override {
3688 InputDispatcherTest::SetUp();
3689
3690 mApplication = std::make_shared<FakeApplicationHandle>();
3691 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3692 "Window without input channel", ADISPLAY_ID_DEFAULT,
3693 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
3694
3695 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3696 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3697 // It's perfectly valid for this window to not have an associated input channel
3698
3699 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
3700 ADISPLAY_ID_DEFAULT);
3701 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
3702
3703 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3704 }
3705
3706protected:
3707 std::shared_ptr<FakeApplicationHandle> mApplication;
3708 sp<FakeWindowHandle> mNoInputWindow;
3709 sp<FakeWindowHandle> mBottomWindow;
3710};
3711
3712TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
3713 PointF touchedPoint = {10, 10};
3714
3715 NotifyMotionArgs motionArgs =
3716 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3717 ADISPLAY_ID_DEFAULT, {touchedPoint});
3718 mDispatcher->notifyMotion(&motionArgs);
3719
3720 mNoInputWindow->assertNoEvents();
3721 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
3722 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
3723 // and therefore should prevent mBottomWindow from receiving touches
3724 mBottomWindow->assertNoEvents();
3725}
3726
3727/**
3728 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
3729 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
3730 */
3731TEST_F(InputDispatcherMultiWindowOcclusionTests,
3732 NoInputChannelFeature_DropsTouchesWithValidChannel) {
3733 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3734 "Window with input channel and NO_INPUT_CHANNEL",
3735 ADISPLAY_ID_DEFAULT);
3736
3737 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3738 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3739 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3740
3741 PointF touchedPoint = {10, 10};
3742
3743 NotifyMotionArgs motionArgs =
3744 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3745 ADISPLAY_ID_DEFAULT, {touchedPoint});
3746 mDispatcher->notifyMotion(&motionArgs);
3747
3748 mNoInputWindow->assertNoEvents();
3749 mBottomWindow->assertNoEvents();
3750}
3751
Vishnu Nair958da932020-08-21 17:12:37 -07003752class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
3753protected:
3754 std::shared_ptr<FakeApplicationHandle> mApp;
3755 sp<FakeWindowHandle> mWindow;
3756 sp<FakeWindowHandle> mMirror;
3757
3758 virtual void SetUp() override {
3759 InputDispatcherTest::SetUp();
3760 mApp = std::make_shared<FakeApplicationHandle>();
3761 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3762 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
3763 mWindow->getToken());
3764 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
3765 mWindow->setFocusable(true);
3766 mMirror->setFocusable(true);
3767 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3768 }
3769};
3770
3771TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
3772 // Request focus on a mirrored window
3773 setFocusedWindow(mMirror);
3774
3775 // window gets focused
3776 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3778 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003779 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
3780}
3781
3782// A focused & mirrored window remains focused only if the window and its mirror are both
3783// focusable.
3784TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
3785 setFocusedWindow(mMirror);
3786
3787 // window gets focused
3788 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3790 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003791 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3793 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003794 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3795
3796 mMirror->setFocusable(false);
3797 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3798
3799 // window loses focus since one of the windows associated with the token in not focusable
3800 mWindow->consumeFocusEvent(false);
3801
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003802 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3803 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003804 mWindow->assertNoEvents();
3805}
3806
3807// A focused & mirrored window remains focused until the window and its mirror both become
3808// invisible.
3809TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
3810 setFocusedWindow(mMirror);
3811
3812 // window gets focused
3813 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3815 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003816 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3818 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003819 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3820
3821 mMirror->setVisible(false);
3822 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3823
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3825 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003826 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3828 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003829 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3830
3831 mWindow->setVisible(false);
3832 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3833
3834 // window loses focus only after all windows associated with the token become invisible.
3835 mWindow->consumeFocusEvent(false);
3836
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003837 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3838 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003839 mWindow->assertNoEvents();
3840}
3841
3842// A focused & mirrored window remains focused until both windows are removed.
3843TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
3844 setFocusedWindow(mMirror);
3845
3846 // window gets focused
3847 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3849 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003850 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3852 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003853 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3854
3855 // single window is removed but the window token remains focused
3856 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
3857
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3859 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003860 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003861 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3862 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003863 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3864
3865 // Both windows are removed
3866 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3867 mWindow->consumeFocusEvent(false);
3868
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003869 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3870 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003871 mWindow->assertNoEvents();
3872}
3873
3874// Focus request can be pending until one window becomes visible.
3875TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
3876 // Request focus on an invisible mirror.
3877 mWindow->setVisible(false);
3878 mMirror->setVisible(false);
3879 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3880 setFocusedWindow(mMirror);
3881
3882 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003884 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003885 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003886
3887 mMirror->setVisible(true);
3888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3889
3890 // window gets focused
3891 mWindow->consumeFocusEvent(true);
3892 // window gets the pending key event
3893 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3894}
Prabir Pradhan99987712020-11-10 18:43:05 -08003895
3896class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
3897protected:
3898 std::shared_ptr<FakeApplicationHandle> mApp;
3899 sp<FakeWindowHandle> mWindow;
3900 sp<FakeWindowHandle> mSecondWindow;
3901
3902 void SetUp() override {
3903 InputDispatcherTest::SetUp();
3904 mApp = std::make_shared<FakeApplicationHandle>();
3905 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3906 mWindow->setFocusable(true);
3907 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
3908 mSecondWindow->setFocusable(true);
3909
3910 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
3911 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
3912
3913 setFocusedWindow(mWindow);
3914 mWindow->consumeFocusEvent(true);
3915 }
3916
3917 void notifyPointerCaptureChanged(bool enabled) {
3918 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(enabled);
3919 mDispatcher->notifyPointerCaptureChanged(&args);
3920 }
3921
3922 void requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window, bool enabled) {
3923 mDispatcher->requestPointerCapture(window->getToken(), enabled);
3924 mFakePolicy->waitForSetPointerCapture(enabled);
3925 notifyPointerCaptureChanged(enabled);
3926 window->consumeCaptureEvent(enabled);
3927 }
3928};
3929
3930TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
3931 // Ensure that capture cannot be obtained for unfocused windows.
3932 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
3933 mFakePolicy->assertSetPointerCaptureNotCalled();
3934 mSecondWindow->assertNoEvents();
3935
3936 // Ensure that capture can be enabled from the focus window.
3937 requestAndVerifyPointerCapture(mWindow, true);
3938
3939 // Ensure that capture cannot be disabled from a window that does not have capture.
3940 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
3941 mFakePolicy->assertSetPointerCaptureNotCalled();
3942
3943 // Ensure that capture can be disabled from the window with capture.
3944 requestAndVerifyPointerCapture(mWindow, false);
3945}
3946
3947TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
3948 requestAndVerifyPointerCapture(mWindow, true);
3949
3950 setFocusedWindow(mSecondWindow);
3951
3952 // Ensure that the capture disabled event was sent first.
3953 mWindow->consumeCaptureEvent(false);
3954 mWindow->consumeFocusEvent(false);
3955 mSecondWindow->consumeFocusEvent(true);
3956 mFakePolicy->waitForSetPointerCapture(false);
3957
3958 // Ensure that additional state changes from InputReader are not sent to the window.
3959 notifyPointerCaptureChanged(false);
3960 notifyPointerCaptureChanged(true);
3961 notifyPointerCaptureChanged(false);
3962 mWindow->assertNoEvents();
3963 mSecondWindow->assertNoEvents();
3964 mFakePolicy->assertSetPointerCaptureNotCalled();
3965}
3966
3967TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
3968 requestAndVerifyPointerCapture(mWindow, true);
3969
3970 // InputReader unexpectedly disables and enables pointer capture.
3971 notifyPointerCaptureChanged(false);
3972 notifyPointerCaptureChanged(true);
3973
3974 // Ensure that Pointer Capture is disabled.
3975 mWindow->consumeCaptureEvent(false);
3976 mWindow->assertNoEvents();
3977}
3978
Garfield Tane84e6f92019-08-29 17:28:41 -07003979} // namespace android::inputdispatcher