blob: bf05b9ff41c7046d72aecd3a69adb110843bb7ce [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>
Michael Wrightd02c5b62014-02-10 15:10:22 -080022#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100023#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080024#include <linux/input.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100025
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:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100074 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080075
76public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100077 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080078
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080079 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080080 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
81 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080082 }
83
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080084 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080085 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
86 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080087 }
88
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070089 void assertFilterInputEventWasNotCalled() {
90 std::scoped_lock lock(mLock);
91 ASSERT_EQ(nullptr, mFilteredEvent);
92 }
Michael Wrightd02c5b62014-02-10 15:10:22 -080093
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080094 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070095 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080096 ASSERT_TRUE(mConfigurationChangedTime)
97 << "Timed out waiting for configuration changed call";
98 ASSERT_EQ(*mConfigurationChangedTime, when);
99 mConfigurationChangedTime = std::nullopt;
100 }
101
102 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700103 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800104 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800105 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800106 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
107 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
108 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
109 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
110 mLastNotifySwitch = std::nullopt;
111 }
112
chaviwfd6d3512019-03-25 13:23:49 -0700113 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700114 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800115 ASSERT_EQ(touchedToken, mOnPointerDownToken);
116 mOnPointerDownToken.clear();
117 }
118
119 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700120 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800121 ASSERT_TRUE(mOnPointerDownToken == nullptr)
122 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700123 }
124
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700125 // This function must be called soon after the expected ANR timer starts,
126 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500127 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700128 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500129 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
130 std::shared_ptr<InputApplicationHandle> application;
131 { // acquire lock
132 std::unique_lock lock(mLock);
133 android::base::ScopedLockAssertion assumeLocked(mLock);
134 ASSERT_NO_FATAL_FAILURE(
135 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
136 } // release lock
137 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700138 }
139
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500140 void assertNotifyConnectionUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
141 const sp<IBinder>& expectedConnectionToken) {
142 sp<IBinder> connectionToken = getUnresponsiveConnectionToken(timeout);
143 ASSERT_EQ(expectedConnectionToken, connectionToken);
144 }
145
146 void assertNotifyConnectionResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
147 sp<IBinder> connectionToken = getResponsiveConnectionToken();
148 ASSERT_EQ(expectedConnectionToken, connectionToken);
149 }
150
151 sp<IBinder> getUnresponsiveConnectionToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700152 std::unique_lock lock(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700153 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500154 return getAnrTokenLockedInterruptible(timeout, mAnrConnectionTokens, lock);
155 }
156
157 sp<IBinder> getResponsiveConnectionToken() {
158 std::unique_lock lock(mLock);
159 android::base::ScopedLockAssertion assumeLocked(mLock);
160 return getAnrTokenLockedInterruptible(0s, mResponsiveConnectionTokens, lock);
161 }
162
163 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
164 // for a specific container to become non-empty. When the container is non-empty, return the
165 // first entry from the container and erase it.
166 template <class T>
167 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
168 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
169 const std::chrono::time_point start = std::chrono::steady_clock::now();
170 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700171
172 // If there is an ANR, Dispatcher won't be idle because there are still events
173 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
174 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500175 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
176 // to provide it some time to act. 100ms seems reasonable.
177 mNotifyAnr.wait_for(lock, timeToWait,
178 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700179 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500180 if (storage.empty()) {
181 ADD_FAILURE() << "Did not receive the ANR callback";
182 return nullptr;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700183 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700184 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
185 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700186 if (std::chrono::abs(timeout - waited) > 100ms) {
187 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
188 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
189 << "ms, but waited "
190 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
191 << "ms instead";
192 }
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500193 T token = storage.front();
194 storage.pop();
195 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700196 }
197
198 void assertNotifyAnrWasNotCalled() {
199 std::scoped_lock lock(mLock);
200 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500201 ASSERT_TRUE(mAnrConnectionTokens.empty());
202 ASSERT_TRUE(mResponsiveConnectionTokens.empty())
203 << "ANR was not called, but please also consume the 'connection is responsive' "
204 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205 }
206
Garfield Tan1c7bc862020-01-28 13:24:04 -0800207 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
208 mConfig.keyRepeatTimeout = timeout;
209 mConfig.keyRepeatDelay = delay;
210 }
211
Prabir Pradhan99987712020-11-10 18:43:05 -0800212 void waitForSetPointerCapture(bool enabled) {
213 std::unique_lock lock(mLock);
214 base::ScopedLockAssertion assumeLocked(mLock);
215
216 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
217 [this, enabled]() REQUIRES(mLock) {
218 return mPointerCaptureEnabled &&
219 *mPointerCaptureEnabled ==
220 enabled;
221 })) {
222 FAIL() << "Timed out waiting for setPointerCapture(" << enabled << ") to be called.";
223 }
224 mPointerCaptureEnabled.reset();
225 }
226
227 void assertSetPointerCaptureNotCalled() {
228 std::unique_lock lock(mLock);
229 base::ScopedLockAssertion assumeLocked(mLock);
230
231 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
232 FAIL() << "Expected setPointerCapture(enabled) to not be called, but was called. "
233 "enabled = "
234 << *mPointerCaptureEnabled;
235 }
236 mPointerCaptureEnabled.reset();
237 }
238
Michael Wrightd02c5b62014-02-10 15:10:22 -0800239private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700240 std::mutex mLock;
241 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
242 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
243 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
244 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800245
Prabir Pradhan99987712020-11-10 18:43:05 -0800246 std::condition_variable mPointerCaptureChangedCondition;
247 std::optional<bool> mPointerCaptureEnabled GUARDED_BY(mLock);
248
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700249 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700250 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500251 std::queue<sp<IBinder>> mAnrConnectionTokens GUARDED_BY(mLock);
252 std::queue<sp<IBinder>> mResponsiveConnectionTokens GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700253 std::condition_variable mNotifyAnr;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700254
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600255 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700256 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800257 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800258 }
259
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500260 void notifyConnectionUnresponsive(const sp<IBinder>& connectionToken,
261 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700262 std::scoped_lock lock(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500263 mAnrConnectionTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700264 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500265 }
266
267 void notifyConnectionResponsive(const sp<IBinder>& connectionToken) override {
268 std::scoped_lock lock(mLock);
269 mResponsiveConnectionTokens.push(connectionToken);
270 mNotifyAnr.notify_all();
271 }
272
273 void notifyNoFocusedWindowAnr(
274 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
275 std::scoped_lock lock(mLock);
276 mAnrApplications.push(applicationHandle);
277 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800278 }
279
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600280 void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800281
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600282 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700283
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600284 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000285
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600286 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800287 *outConfig = mConfig;
288 }
289
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600290 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700291 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800292 switch (inputEvent->getType()) {
293 case AINPUT_EVENT_TYPE_KEY: {
294 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800295 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800296 break;
297 }
298
299 case AINPUT_EVENT_TYPE_MOTION: {
300 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800301 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800302 break;
303 }
304 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800305 return true;
306 }
307
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600308 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800309
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600310 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800311
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600312 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 return 0;
314 }
315
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600316 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800317 return false;
318 }
319
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600320 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
321 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700322 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800323 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
324 * essentially a passthrough for notifySwitch.
325 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800326 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800327 }
328
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600329 void pokeUserActivity(nsecs_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800330
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600331 bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; }
Jackal Guof9696682018-10-05 12:23:23 +0800332
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600333 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700334 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700335 mOnPointerDownToken = newToken;
336 }
337
Prabir Pradhan99987712020-11-10 18:43:05 -0800338 void setPointerCapture(bool enabled) override {
339 std::scoped_lock lock(mLock);
340 mPointerCaptureEnabled = {enabled};
341 mPointerCaptureChangedCondition.notify_all();
342 }
343
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800344 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
345 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700346 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800347 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
348 ASSERT_EQ(mFilteredEvent->getType(), type);
349
350 if (type == AINPUT_EVENT_TYPE_KEY) {
351 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
352 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
353 EXPECT_EQ(keyEvent.getAction(), action);
354 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
355 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
356 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
357 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
358 EXPECT_EQ(motionEvent.getAction(), action);
359 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
360 } else {
361 FAIL() << "Unknown type: " << type;
362 }
363
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800364 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800365 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800366};
367
Michael Wrightd02c5b62014-02-10 15:10:22 -0800368// --- InputDispatcherTest ---
369
370class InputDispatcherTest : public testing::Test {
371protected:
372 sp<FakeInputDispatcherPolicy> mFakePolicy;
373 sp<InputDispatcher> mDispatcher;
374
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700375 virtual void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800376 mFakePolicy = new FakeInputDispatcherPolicy();
377 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800378 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000379 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700380 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800381 }
382
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700383 virtual void TearDown() override {
384 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800385 mFakePolicy.clear();
386 mDispatcher.clear();
387 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700388
389 /**
390 * Used for debugging when writing the test
391 */
392 void dumpDispatcherState() {
393 std::string dump;
394 mDispatcher->dump(dump);
395 std::stringstream ss(dump);
396 std::string to;
397
398 while (std::getline(ss, to, '\n')) {
399 ALOGE("%s", to.c_str());
400 }
401 }
Vishnu Nair958da932020-08-21 17:12:37 -0700402
403 void setFocusedWindow(const sp<InputWindowHandle>& window,
404 const sp<InputWindowHandle>& focusedWindow = nullptr) {
405 FocusRequest request;
406 request.token = window->getToken();
407 if (focusedWindow) {
408 request.focusedToken = focusedWindow->getToken();
409 }
410 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
411 request.displayId = window->getInfo()->displayId;
412 mDispatcher->setFocusedWindow(request);
413 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800414};
415
Michael Wrightd02c5b62014-02-10 15:10:22 -0800416TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
417 KeyEvent event;
418
419 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800420 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
421 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600422 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
423 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800424 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700425 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800426 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800427 << "Should reject key events with undefined action.";
428
429 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800430 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
431 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600432 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800433 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700434 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800435 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800436 << "Should reject key events with ACTION_MULTIPLE.";
437}
438
439TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
440 MotionEvent event;
441 PointerProperties pointerProperties[MAX_POINTERS + 1];
442 PointerCoords pointerCoords[MAX_POINTERS + 1];
443 for (int i = 0; i <= MAX_POINTERS; i++) {
444 pointerProperties[i].clear();
445 pointerProperties[i].id = i;
446 pointerCoords[i].clear();
447 }
448
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800449 // Some constants commonly used below
450 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
451 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
452 constexpr int32_t metaState = AMETA_NONE;
453 constexpr MotionClassification classification = MotionClassification::NONE;
454
chaviw9eaa22c2020-07-01 16:21:27 -0700455 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800456 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800457 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700458 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
459 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600460 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700461 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800462 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700463 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800464 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800465 << "Should reject motion events with undefined action.";
466
467 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800468 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700469 AMOTION_EVENT_ACTION_POINTER_DOWN |
470 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700471 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
472 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
473 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
474 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800475 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700476 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800477 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800478 << "Should reject motion events with pointer down index too large.";
479
Garfield Tanfbe732e2020-01-24 11:26:14 -0800480 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700481 AMOTION_EVENT_ACTION_POINTER_DOWN |
482 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700483 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
484 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
485 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
486 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800487 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700488 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800489 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800490 << "Should reject motion events with pointer down index too small.";
491
492 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800493 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700494 AMOTION_EVENT_ACTION_POINTER_UP |
495 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700496 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
497 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
498 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
499 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800500 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700501 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800502 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800503 << "Should reject motion events with pointer up index too large.";
504
Garfield Tanfbe732e2020-01-24 11:26:14 -0800505 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700506 AMOTION_EVENT_ACTION_POINTER_UP |
507 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700508 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
509 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
510 ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties,
511 pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800512 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700513 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800514 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800515 << "Should reject motion events with pointer up index too small.";
516
517 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800518 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
519 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700520 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
521 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700522 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800523 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700524 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800525 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800526 << "Should reject motion events with 0 pointers.";
527
Garfield Tanfbe732e2020-01-24 11:26:14 -0800528 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
529 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700530 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
531 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700532 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800533 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700534 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800535 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800536 << "Should reject motion events with more than MAX_POINTERS pointers.";
537
538 // Rejects motion events with invalid pointer ids.
539 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800540 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
541 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700542 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
543 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700544 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800545 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700546 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800547 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800548 << "Should reject motion events with pointer ids less than 0.";
549
550 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800551 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
552 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700553 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
554 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700555 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800556 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700557 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800558 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800559 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
560
561 // Rejects motion events with duplicate pointer ids.
562 pointerProperties[0].id = 1;
563 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800564 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
565 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700566 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
567 AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700568 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800569 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700570 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800571 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800572 << "Should reject motion events with duplicate pointer ids.";
573}
574
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800575/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
576
577TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
578 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800579 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800580 mDispatcher->notifyConfigurationChanged(&args);
581 ASSERT_TRUE(mDispatcher->waitForIdle());
582
583 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
584}
585
586TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800587 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
588 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800589 mDispatcher->notifySwitch(&args);
590
591 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
592 args.policyFlags |= POLICY_FLAG_TRUSTED;
593 mFakePolicy->assertNotifySwitchWasCalled(args);
594}
595
Arthur Hungb92218b2018-08-14 12:00:21 +0800596// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700597static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700598static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800599
600class FakeApplicationHandle : public InputApplicationHandle {
601public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700602 FakeApplicationHandle() {
603 mInfo.name = "Fake Application";
604 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500605 mInfo.dispatchingTimeoutMillis =
606 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700607 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800608 virtual ~FakeApplicationHandle() {}
609
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000610 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700611
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500612 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
613 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700614 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800615};
616
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800617class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800618public:
Garfield Tan15601662020-09-22 15:32:38 -0700619 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800620 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700621 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800622 }
623
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800624 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700625 InputEvent* event;
626 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
627 if (!consumeSeq) {
628 return nullptr;
629 }
630 finishEvent(*consumeSeq);
631 return event;
632 }
633
634 /**
635 * Receive an event without acknowledging it.
636 * Return the sequence number that could later be used to send finished signal.
637 */
638 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800639 uint32_t consumeSeq;
640 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800641
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800642 std::chrono::time_point start = std::chrono::steady_clock::now();
643 status_t status = WOULD_BLOCK;
644 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800645 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800646 &event);
647 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
648 if (elapsed > 100ms) {
649 break;
650 }
651 }
652
653 if (status == WOULD_BLOCK) {
654 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700655 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800656 }
657
658 if (status != OK) {
659 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700660 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800661 }
662 if (event == nullptr) {
663 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700664 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800665 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700666 if (outEvent != nullptr) {
667 *outEvent = event;
668 }
669 return consumeSeq;
670 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800671
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700672 /**
673 * To be used together with "receiveEvent" to complete the consumption of an event.
674 */
675 void finishEvent(uint32_t consumeSeq) {
676 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
677 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800678 }
679
680 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
681 int32_t expectedFlags) {
682 InputEvent* event = consume();
683
684 ASSERT_NE(nullptr, event) << mName.c_str()
685 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800686 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700687 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800688 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800689
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800690 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800691
Tiger Huang8664f8c2018-10-11 19:14:35 +0800692 switch (expectedEventType) {
693 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800694 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
695 EXPECT_EQ(expectedAction, keyEvent.getAction());
696 EXPECT_EQ(expectedFlags, keyEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800697 break;
698 }
699 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800700 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
701 EXPECT_EQ(expectedAction, motionEvent.getAction());
702 EXPECT_EQ(expectedFlags, motionEvent.getFlags());
Tiger Huang8664f8c2018-10-11 19:14:35 +0800703 break;
704 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100705 case AINPUT_EVENT_TYPE_FOCUS: {
706 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
707 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800708 case AINPUT_EVENT_TYPE_CAPTURE: {
709 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
710 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800711 default: {
712 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
713 }
714 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800715 }
716
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100717 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
718 InputEvent* event = consume();
719 ASSERT_NE(nullptr, event) << mName.c_str()
720 << ": consumer should have returned non-NULL event.";
721 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
722 << "Got " << inputEventTypeToString(event->getType())
723 << " event instead of FOCUS event";
724
725 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
726 << mName.c_str() << ": event displayId should always be NONE.";
727
728 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
729 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
730 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
731 }
732
Prabir Pradhan99987712020-11-10 18:43:05 -0800733 void consumeCaptureEvent(bool hasCapture) {
734 const InputEvent* event = consume();
735 ASSERT_NE(nullptr, event) << mName.c_str()
736 << ": consumer should have returned non-NULL event.";
737 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
738 << "Got " << inputEventTypeToString(event->getType())
739 << " event instead of CAPTURE event";
740
741 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
742 << mName.c_str() << ": event displayId should always be NONE.";
743
744 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
745 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
746 }
747
chaviwd1c23182019-12-20 18:44:56 -0800748 void assertNoEvents() {
749 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700750 if (event == nullptr) {
751 return;
752 }
753 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
754 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
755 ADD_FAILURE() << "Received key event "
756 << KeyEvent::actionToString(keyEvent.getAction());
757 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
758 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
759 ADD_FAILURE() << "Received motion event "
760 << MotionEvent::actionToString(motionEvent.getAction());
761 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
762 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
763 ADD_FAILURE() << "Received focus event, hasFocus = "
764 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800765 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
766 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
767 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
768 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700769 }
770 FAIL() << mName.c_str()
771 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800772 }
773
774 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
775
776protected:
777 std::unique_ptr<InputConsumer> mConsumer;
778 PreallocatedInputEventFactory mEventFactory;
779
780 std::string mName;
781};
782
783class FakeWindowHandle : public InputWindowHandle {
784public:
785 static const int32_t WIDTH = 600;
786 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800787
Chris Yea209fde2020-07-22 13:54:51 -0700788 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800789 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500790 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800791 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500792 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700793 base::Result<std::unique_ptr<InputChannel>> channel =
794 dispatcher->createInputChannel(name);
795 token = (*channel)->getConnectionToken();
796 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800797 }
798
799 inputApplicationHandle->updateInfo();
800 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
801
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500802 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700803 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800804 mInfo.name = name;
Michael Wright44753b12020-07-08 13:48:11 +0100805 mInfo.type = InputWindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500806 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
chaviwd1c23182019-12-20 18:44:56 -0800807 mInfo.frameLeft = 0;
808 mInfo.frameTop = 0;
809 mInfo.frameRight = WIDTH;
810 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700811 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800812 mInfo.globalScaleFactor = 1.0;
813 mInfo.touchableRegion.clear();
814 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
815 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700816 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800817 mInfo.hasWallpaper = false;
818 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800819 mInfo.ownerPid = INJECTOR_PID;
820 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800821 mInfo.displayId = displayId;
822 }
823
824 virtual bool updateInfo() { return true; }
825
Vishnu Nair47074b82020-08-14 11:54:47 -0700826 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800827
Vishnu Nair958da932020-08-21 17:12:37 -0700828 void setVisible(bool visible) { mInfo.visible = visible; }
829
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700830 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500831 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700832 }
833
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700834 void setPaused(bool paused) { mInfo.paused = paused; }
835
chaviwd1c23182019-12-20 18:44:56 -0800836 void setFrame(const Rect& frame) {
837 mInfo.frameLeft = frame.left;
838 mInfo.frameTop = frame.top;
839 mInfo.frameRight = frame.right;
840 mInfo.frameBottom = frame.bottom;
chaviw1ff3d1e2020-07-01 15:53:47 -0700841 mInfo.transform.set(frame.left, frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800842 mInfo.touchableRegion.clear();
843 mInfo.addTouchableRegion(frame);
844 }
845
Michael Wright44753b12020-07-08 13:48:11 +0100846 void setFlags(Flags<InputWindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800847
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500848 void setInputFeatures(InputWindowInfo::Feature features) { mInfo.inputFeatures = features; }
849
chaviw9eaa22c2020-07-01 16:21:27 -0700850 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
851 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
852 }
853
854 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700855
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800856 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
857 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
858 expectedFlags);
859 }
860
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700861 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
862 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
863 }
864
Svet Ganov5d3bc372020-01-26 23:11:07 -0800865 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000866 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800867 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
868 expectedFlags);
869 }
870
871 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000872 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800873 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
874 expectedFlags);
875 }
876
877 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000878 int32_t expectedFlags = 0) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800879 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
880 expectedFlags);
881 }
882
Svet Ganov5d3bc372020-01-26 23:11:07 -0800883 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000884 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
885 int32_t expectedFlags = 0) {
886 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
887 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800888 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
889 }
890
891 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000892 int32_t expectedFlags = 0) {
893 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
894 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800895 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
896 }
897
898 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000899 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +0000900 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
901 expectedFlags);
902 }
903
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500904 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
905 int32_t expectedFlags = 0) {
906 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
907 expectedFlags);
908 }
909
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100910 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
911 ASSERT_NE(mInputReceiver, nullptr)
912 << "Cannot consume events from a window with no receiver";
913 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
914 }
915
Prabir Pradhan99987712020-11-10 18:43:05 -0800916 void consumeCaptureEvent(bool hasCapture) {
917 ASSERT_NE(mInputReceiver, nullptr)
918 << "Cannot consume events from a window with no receiver";
919 mInputReceiver->consumeCaptureEvent(hasCapture);
920 }
921
chaviwd1c23182019-12-20 18:44:56 -0800922 void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
923 int32_t expectedFlags) {
924 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
925 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
926 expectedFlags);
927 }
928
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700929 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700930 if (mInputReceiver == nullptr) {
931 ADD_FAILURE() << "Invalid receive event on window with no receiver";
932 return std::nullopt;
933 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700934 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700935 }
936
937 void finishEvent(uint32_t sequenceNum) {
938 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
939 mInputReceiver->finishEvent(sequenceNum);
940 }
941
chaviwaf87b3e2019-10-01 16:59:28 -0700942 InputEvent* consume() {
943 if (mInputReceiver == nullptr) {
944 return nullptr;
945 }
946 return mInputReceiver->consume();
947 }
948
Arthur Hungb92218b2018-08-14 12:00:21 +0800949 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500950 if (mInputReceiver == nullptr &&
951 mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
952 return; // Can't receive events if the window does not have input channel
953 }
954 ASSERT_NE(nullptr, mInputReceiver)
955 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -0800956 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +0800957 }
958
chaviwaf87b3e2019-10-01 16:59:28 -0700959 sp<IBinder> getToken() { return mInfo.token; }
960
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100961 const std::string& getName() { return mName; }
962
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000963 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
964 mInfo.ownerPid = ownerPid;
965 mInfo.ownerUid = ownerUid;
966 }
967
chaviwd1c23182019-12-20 18:44:56 -0800968private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100969 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -0800970 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700971 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800972};
973
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700974std::atomic<int32_t> FakeWindowHandle::sId{1};
975
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800976static InputEventInjectionResult injectKey(
977 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
978 int32_t displayId = ADISPLAY_ID_NONE,
979 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
980 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800981 KeyEvent event;
982 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
983
984 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800985 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700986 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
987 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800988
989 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700990 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
991 injectionTimeout,
992 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
Arthur Hungb92218b2018-08-14 12:00:21 +0800993}
994
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800995static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
996 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700997 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
998}
999
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001000static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
1001 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001002 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1003}
1004
Garfield Tandf26e862020-07-01 20:18:19 -07001005class PointerBuilder {
1006public:
1007 PointerBuilder(int32_t id, int32_t toolType) {
1008 mProperties.clear();
1009 mProperties.id = id;
1010 mProperties.toolType = toolType;
1011 mCoords.clear();
1012 }
1013
1014 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1015
1016 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1017
1018 PointerBuilder& axis(int32_t axis, float value) {
1019 mCoords.setAxisValue(axis, value);
1020 return *this;
1021 }
1022
1023 PointerProperties buildProperties() const { return mProperties; }
1024
1025 PointerCoords buildCoords() const { return mCoords; }
1026
1027private:
1028 PointerProperties mProperties;
1029 PointerCoords mCoords;
1030};
1031
1032class MotionEventBuilder {
1033public:
1034 MotionEventBuilder(int32_t action, int32_t source) {
1035 mAction = action;
1036 mSource = source;
1037 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1038 }
1039
1040 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1041 mEventTime = eventTime;
1042 return *this;
1043 }
1044
1045 MotionEventBuilder& displayId(int32_t displayId) {
1046 mDisplayId = displayId;
1047 return *this;
1048 }
1049
1050 MotionEventBuilder& actionButton(int32_t actionButton) {
1051 mActionButton = actionButton;
1052 return *this;
1053 }
1054
1055 MotionEventBuilder& buttonState(int32_t actionButton) {
1056 mActionButton = actionButton;
1057 return *this;
1058 }
1059
1060 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1061 mRawXCursorPosition = rawXCursorPosition;
1062 return *this;
1063 }
1064
1065 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1066 mRawYCursorPosition = rawYCursorPosition;
1067 return *this;
1068 }
1069
1070 MotionEventBuilder& pointer(PointerBuilder pointer) {
1071 mPointers.push_back(pointer);
1072 return *this;
1073 }
1074
1075 MotionEvent build() {
1076 std::vector<PointerProperties> pointerProperties;
1077 std::vector<PointerCoords> pointerCoords;
1078 for (const PointerBuilder& pointer : mPointers) {
1079 pointerProperties.push_back(pointer.buildProperties());
1080 pointerCoords.push_back(pointer.buildCoords());
1081 }
1082
1083 // Set mouse cursor position for the most common cases to avoid boilerplate.
1084 if (mSource == AINPUT_SOURCE_MOUSE &&
1085 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1086 mPointers.size() == 1) {
1087 mRawXCursorPosition = pointerCoords[0].getX();
1088 mRawYCursorPosition = pointerCoords[0].getY();
1089 }
1090
1091 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001092 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001093 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
1094 mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001095 mButtonState, MotionClassification::NONE, identityTransform,
1096 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
1097 mRawYCursorPosition, mEventTime, mEventTime, mPointers.size(),
1098 pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001099
1100 return event;
1101 }
1102
1103private:
1104 int32_t mAction;
1105 int32_t mSource;
1106 nsecs_t mEventTime;
1107 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1108 int32_t mActionButton{0};
1109 int32_t mButtonState{0};
1110 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1111 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1112
1113 std::vector<PointerBuilder> mPointers;
1114};
1115
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001116static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001117 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1118 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001119 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001120 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1121 injectionTimeout,
1122 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1123}
1124
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001125static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001126 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1127 const PointF& position,
1128 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001129 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1130 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001131 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001132 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001133 MotionEvent event = MotionEventBuilder(action, source)
1134 .displayId(displayId)
1135 .eventTime(eventTime)
1136 .rawXCursorPosition(cursorPosition.x)
1137 .rawYCursorPosition(cursorPosition.y)
1138 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1139 .x(position.x)
1140 .y(position.y))
1141 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001142
1143 // Inject event until dispatch out.
Garfield Tandf26e862020-07-01 20:18:19 -07001144 return injectMotionEvent(dispatcher, event);
Arthur Hungb92218b2018-08-14 12:00:21 +08001145}
1146
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001147static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1148 int32_t source, int32_t displayId,
1149 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001150 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001151}
1152
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001153static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1154 int32_t source, int32_t displayId,
1155 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001156 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001157}
1158
Jackal Guof9696682018-10-05 12:23:23 +08001159static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1160 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1161 // Define a valid key event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001162 NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
1163 POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
1164 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001165
1166 return args;
1167}
1168
chaviwd1c23182019-12-20 18:44:56 -08001169static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1170 const std::vector<PointF>& points) {
1171 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001172 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1173 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1174 }
1175
chaviwd1c23182019-12-20 18:44:56 -08001176 PointerProperties pointerProperties[pointerCount];
1177 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001178
chaviwd1c23182019-12-20 18:44:56 -08001179 for (size_t i = 0; i < pointerCount; i++) {
1180 pointerProperties[i].clear();
1181 pointerProperties[i].id = i;
1182 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001183
chaviwd1c23182019-12-20 18:44:56 -08001184 pointerCoords[i].clear();
1185 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1186 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1187 }
Jackal Guof9696682018-10-05 12:23:23 +08001188
1189 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1190 // Define a valid motion event.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001191 NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001192 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1193 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001194 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1195 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001196 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1197 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001198
1199 return args;
1200}
1201
chaviwd1c23182019-12-20 18:44:56 -08001202static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1203 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1204}
1205
Prabir Pradhan99987712020-11-10 18:43:05 -08001206static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(bool enabled) {
1207 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), enabled);
1208}
1209
Arthur Hungb92218b2018-08-14 12:00:21 +08001210TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001212 sp<FakeWindowHandle> window =
1213 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001214
Arthur Hung72d8dc32020-03-28 00:48:39 +00001215 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1217 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1218 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001219
1220 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001221 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001222}
1223
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001224/**
1225 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1226 * To ensure that window receives only events that were directly inside of it, add
1227 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1228 * when finding touched windows.
1229 * This test serves as a sanity check for the next test, where setInputWindows is
1230 * called twice.
1231 */
1232TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001234 sp<FakeWindowHandle> window =
1235 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1236 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001237 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001238
1239 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001241 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1242 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001244
1245 // Window should receive motion event.
1246 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1247}
1248
1249/**
1250 * Calling setInputWindows twice, with the same info, should not cause any issues.
1251 * To ensure that window receives only events that were directly inside of it, add
1252 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1253 * when finding touched windows.
1254 */
1255TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001256 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001257 sp<FakeWindowHandle> window =
1258 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1259 window->setFrame(Rect(0, 0, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01001260 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001261
1262 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1263 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001265 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1266 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001267 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001268
1269 // Window should receive motion event.
1270 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1271}
1272
Arthur Hungb92218b2018-08-14 12:00:21 +08001273// The foreground window should receive the first touch down event.
1274TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001275 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001276 sp<FakeWindowHandle> windowTop =
1277 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1278 sp<FakeWindowHandle> windowSecond =
1279 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001280
Arthur Hung72d8dc32020-03-28 00:48:39 +00001281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1283 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001285
1286 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001287 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001288 windowSecond->assertNoEvents();
1289}
1290
Garfield Tandf26e862020-07-01 20:18:19 -07001291TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001292 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001293 sp<FakeWindowHandle> windowLeft =
1294 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1295 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001296 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001297 sp<FakeWindowHandle> windowRight =
1298 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1299 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001300 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001301
1302 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1303
1304 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1305
1306 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001308 injectMotionEvent(mDispatcher,
1309 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1310 AINPUT_SOURCE_MOUSE)
1311 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1312 .x(900)
1313 .y(400))
1314 .build()));
1315 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1316 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1317 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1318 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1319
1320 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001322 injectMotionEvent(mDispatcher,
1323 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1324 AINPUT_SOURCE_MOUSE)
1325 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1326 .x(300)
1327 .y(400))
1328 .build()));
1329 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1330 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1331 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1332 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1333 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1334 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1335
1336 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001338 injectMotionEvent(mDispatcher,
1339 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1340 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1341 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1342 .x(300)
1343 .y(400))
1344 .build()));
1345 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1346
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001348 injectMotionEvent(mDispatcher,
1349 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1350 AINPUT_SOURCE_MOUSE)
1351 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1352 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1353 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1354 .x(300)
1355 .y(400))
1356 .build()));
1357 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1358 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1359
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001361 injectMotionEvent(mDispatcher,
1362 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1363 AINPUT_SOURCE_MOUSE)
1364 .buttonState(0)
1365 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1366 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1367 .x(300)
1368 .y(400))
1369 .build()));
1370 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1371 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1372
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001374 injectMotionEvent(mDispatcher,
1375 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1376 .buttonState(0)
1377 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1378 .x(300)
1379 .y(400))
1380 .build()));
1381 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1382
1383 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001385 injectMotionEvent(mDispatcher,
1386 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1387 AINPUT_SOURCE_MOUSE)
1388 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1389 .x(900)
1390 .y(400))
1391 .build()));
1392 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1393 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1394 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1395 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1396 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1397 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1398}
1399
1400// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1401// directly in this test.
1402TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001403 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001404 sp<FakeWindowHandle> window =
1405 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1406 window->setFrame(Rect(0, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001407 window->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001408
1409 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1410
1411 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1412
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001414 injectMotionEvent(mDispatcher,
1415 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1416 AINPUT_SOURCE_MOUSE)
1417 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1418 .x(300)
1419 .y(400))
1420 .build()));
1421 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1422 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1423
1424 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001426 injectMotionEvent(mDispatcher,
1427 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1428 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1429 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1430 .x(300)
1431 .y(400))
1432 .build()));
1433 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1434
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001435 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001436 injectMotionEvent(mDispatcher,
1437 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1438 AINPUT_SOURCE_MOUSE)
1439 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1440 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1441 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1442 .x(300)
1443 .y(400))
1444 .build()));
1445 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1446 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001449 injectMotionEvent(mDispatcher,
1450 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1451 AINPUT_SOURCE_MOUSE)
1452 .buttonState(0)
1453 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1454 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1455 .x(300)
1456 .y(400))
1457 .build()));
1458 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1459 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1460
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001462 injectMotionEvent(mDispatcher,
1463 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1464 .buttonState(0)
1465 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1466 .x(300)
1467 .y(400))
1468 .build()));
1469 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1470
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001472 injectMotionEvent(mDispatcher,
1473 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1474 AINPUT_SOURCE_MOUSE)
1475 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1476 .x(300)
1477 .y(400))
1478 .build()));
1479 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1480 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1481}
1482
Garfield Tan00f511d2019-06-12 16:55:40 -07001483TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001485
1486 sp<FakeWindowHandle> windowLeft =
1487 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1488 windowLeft->setFrame(Rect(0, 0, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001489 windowLeft->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001490 sp<FakeWindowHandle> windowRight =
1491 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1492 windowRight->setFrame(Rect(600, 0, 1200, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001493 windowRight->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001494
1495 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1496
Arthur Hung72d8dc32020-03-28 00:48:39 +00001497 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001498
1499 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1500 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001502 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001503 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001504 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001505 windowRight->assertNoEvents();
1506}
1507
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001508TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001509 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001510 sp<FakeWindowHandle> window =
1511 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001512 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001513
Arthur Hung72d8dc32020-03-28 00:48:39 +00001514 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001515 setFocusedWindow(window);
1516
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001517 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001518
1519 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1520 mDispatcher->notifyKey(&keyArgs);
1521
1522 // Window should receive key down event.
1523 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1524
1525 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1526 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001527 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001528 mDispatcher->notifyDeviceReset(&args);
1529 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1530 AKEY_EVENT_FLAG_CANCELED);
1531}
1532
1533TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001534 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001535 sp<FakeWindowHandle> window =
1536 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1537
Arthur Hung72d8dc32020-03-28 00:48:39 +00001538 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001539
1540 NotifyMotionArgs motionArgs =
1541 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1542 ADISPLAY_ID_DEFAULT);
1543 mDispatcher->notifyMotion(&motionArgs);
1544
1545 // Window should receive motion down event.
1546 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1547
1548 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1549 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001550 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001551 mDispatcher->notifyDeviceReset(&args);
1552 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1553 0 /*expectedFlags*/);
1554}
1555
Svet Ganov5d3bc372020-01-26 23:11:07 -08001556TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001558
1559 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001560 sp<FakeWindowHandle> firstWindow =
1561 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1562 sp<FakeWindowHandle> secondWindow =
1563 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001564
1565 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001566 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001567
1568 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001569 NotifyMotionArgs downMotionArgs =
1570 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1571 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001572 mDispatcher->notifyMotion(&downMotionArgs);
1573 // Only the first window should get the down event
1574 firstWindow->consumeMotionDown();
1575 secondWindow->assertNoEvents();
1576
1577 // Transfer touch focus to the second window
1578 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1579 // The first window gets cancel and the second gets down
1580 firstWindow->consumeMotionCancel();
1581 secondWindow->consumeMotionDown();
1582
1583 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001584 NotifyMotionArgs upMotionArgs =
1585 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1586 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001587 mDispatcher->notifyMotion(&upMotionArgs);
1588 // The first window gets no events and the second gets up
1589 firstWindow->assertNoEvents();
1590 secondWindow->consumeMotionUp();
1591}
1592
1593TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001595
1596 PointF touchPoint = {10, 10};
1597
1598 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001599 sp<FakeWindowHandle> firstWindow =
1600 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1601 sp<FakeWindowHandle> secondWindow =
1602 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001603
1604 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001605 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001606
1607 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001608 NotifyMotionArgs downMotionArgs =
1609 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1610 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001611 mDispatcher->notifyMotion(&downMotionArgs);
1612 // Only the first window should get the down event
1613 firstWindow->consumeMotionDown();
1614 secondWindow->assertNoEvents();
1615
1616 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001617 NotifyMotionArgs pointerDownMotionArgs =
1618 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1619 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1620 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1621 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001622 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1623 // Only the first window should get the pointer down event
1624 firstWindow->consumeMotionPointerDown(1);
1625 secondWindow->assertNoEvents();
1626
1627 // Transfer touch focus to the second window
1628 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1629 // The first window gets cancel and the second gets down and pointer down
1630 firstWindow->consumeMotionCancel();
1631 secondWindow->consumeMotionDown();
1632 secondWindow->consumeMotionPointerDown(1);
1633
1634 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001635 NotifyMotionArgs pointerUpMotionArgs =
1636 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1637 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1638 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1639 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001640 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1641 // The first window gets nothing and the second gets pointer up
1642 firstWindow->assertNoEvents();
1643 secondWindow->consumeMotionPointerUp(1);
1644
1645 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001646 NotifyMotionArgs upMotionArgs =
1647 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1648 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001649 mDispatcher->notifyMotion(&upMotionArgs);
1650 // The first window gets nothing and the second gets up
1651 firstWindow->assertNoEvents();
1652 secondWindow->consumeMotionUp();
1653}
1654
1655TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001657
1658 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001659 sp<FakeWindowHandle> firstWindow =
1660 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001661 firstWindow->setFrame(Rect(0, 0, 600, 400));
Michael Wright44753b12020-07-08 13:48:11 +01001662 firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1663 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001664
1665 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001666 sp<FakeWindowHandle> secondWindow =
1667 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001668 secondWindow->setFrame(Rect(0, 400, 600, 800));
Michael Wright44753b12020-07-08 13:48:11 +01001669 secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
1670 InputWindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001671
1672 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001673 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001674
1675 PointF pointInFirst = {300, 200};
1676 PointF pointInSecond = {300, 600};
1677
1678 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001679 NotifyMotionArgs firstDownMotionArgs =
1680 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1681 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001682 mDispatcher->notifyMotion(&firstDownMotionArgs);
1683 // Only the first window should get the down event
1684 firstWindow->consumeMotionDown();
1685 secondWindow->assertNoEvents();
1686
1687 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001688 NotifyMotionArgs secondDownMotionArgs =
1689 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1690 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1691 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1692 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001693 mDispatcher->notifyMotion(&secondDownMotionArgs);
1694 // The first window gets a move and the second a down
1695 firstWindow->consumeMotionMove();
1696 secondWindow->consumeMotionDown();
1697
1698 // Transfer touch focus to the second window
1699 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1700 // The first window gets cancel and the new gets pointer down (it already saw down)
1701 firstWindow->consumeMotionCancel();
1702 secondWindow->consumeMotionPointerDown(1);
1703
1704 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001705 NotifyMotionArgs pointerUpMotionArgs =
1706 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1707 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1708 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1709 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001710 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1711 // The first window gets nothing and the second gets pointer up
1712 firstWindow->assertNoEvents();
1713 secondWindow->consumeMotionPointerUp(1);
1714
1715 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001716 NotifyMotionArgs upMotionArgs =
1717 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1718 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001719 mDispatcher->notifyMotion(&upMotionArgs);
1720 // The first window gets nothing and the second gets up
1721 firstWindow->assertNoEvents();
1722 secondWindow->consumeMotionUp();
1723}
1724
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001725TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001727 sp<FakeWindowHandle> window =
1728 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1729
Vishnu Nair47074b82020-08-14 11:54:47 -07001730 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001731 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001732 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001733
1734 window->consumeFocusEvent(true);
1735
1736 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1737 mDispatcher->notifyKey(&keyArgs);
1738
1739 // Window should receive key down event.
1740 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1741}
1742
1743TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
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 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1751 mDispatcher->notifyKey(&keyArgs);
1752 mDispatcher->waitForIdle();
1753
1754 window->assertNoEvents();
1755}
1756
1757// If a window is touchable, but does not have focus, it should receive motion events, but not keys
1758TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07001759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001760 sp<FakeWindowHandle> window =
1761 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1762
Arthur Hung72d8dc32020-03-28 00:48:39 +00001763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001764
1765 // Send key
1766 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1767 mDispatcher->notifyKey(&keyArgs);
1768 // Send motion
1769 NotifyMotionArgs motionArgs =
1770 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1771 ADISPLAY_ID_DEFAULT);
1772 mDispatcher->notifyMotion(&motionArgs);
1773
1774 // Window should receive only the motion event
1775 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1776 window->assertNoEvents(); // Key event or focus event will not be received
1777}
1778
chaviwd1c23182019-12-20 18:44:56 -08001779class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00001780public:
1781 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08001782 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07001783 base::Result<std::unique_ptr<InputChannel>> channel =
1784 dispatcher->createInputMonitor(displayId, isGestureMonitor, name);
1785 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00001786 }
1787
chaviwd1c23182019-12-20 18:44:56 -08001788 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1789
1790 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1791 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
1792 expectedDisplayId, expectedFlags);
1793 }
1794
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001795 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
1796
1797 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1798
chaviwd1c23182019-12-20 18:44:56 -08001799 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1800 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
1801 expectedDisplayId, expectedFlags);
1802 }
1803
1804 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1805 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
1806 expectedDisplayId, expectedFlags);
1807 }
1808
1809 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1810
1811private:
1812 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00001813};
1814
1815// Tests for gesture monitors
1816TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001817 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001818 sp<FakeWindowHandle> window =
1819 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001820 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001821
chaviwd1c23182019-12-20 18:44:56 -08001822 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1823 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001824
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001826 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001828 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001829 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001830}
1831
1832TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07001833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001834 sp<FakeWindowHandle> window =
1835 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1836
1837 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001838 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00001839
Arthur Hung72d8dc32020-03-28 00:48:39 +00001840 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001841 setFocusedWindow(window);
1842
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001843 window->consumeFocusEvent(true);
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, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
1849 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001850 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001851 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00001852}
1853
1854TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00001856 sp<FakeWindowHandle> window =
1857 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00001859
chaviwd1c23182019-12-20 18:44:56 -08001860 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
1861 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00001862
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001864 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00001866 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08001867 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001868
1869 window->releaseChannel();
1870
chaviwd1c23182019-12-20 18:44:56 -08001871 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00001872
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00001874 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001875 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08001876 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00001877}
1878
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001879TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
1880 FakeMonitorReceiver monitor =
1881 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
1882 true /*isGestureMonitor*/);
1883
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001885 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
1886 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
1887 ASSERT_TRUE(consumeSeq);
1888
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001889 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(DISPATCHING_TIMEOUT,
1890 monitor.getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001891 monitor.finishEvent(*consumeSeq);
1892 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001893 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(monitor.getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001894}
1895
chaviw81e2bb92019-12-18 15:03:51 -08001896TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001897 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08001898 sp<FakeWindowHandle> window =
1899 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1900
Arthur Hung72d8dc32020-03-28 00:48:39 +00001901 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08001902
1903 NotifyMotionArgs motionArgs =
1904 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1905 ADISPLAY_ID_DEFAULT);
1906
1907 mDispatcher->notifyMotion(&motionArgs);
1908 // Window should receive motion down event.
1909 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1910
1911 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001912 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08001913 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1914 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
1915 motionArgs.pointerCoords[0].getX() - 10);
1916
1917 mDispatcher->notifyMotion(&motionArgs);
1918 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
1919 0 /*expectedFlags*/);
1920}
1921
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001922/**
1923 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
1924 * the device default right away. In the test scenario, we check both the default value,
1925 * and the action of enabling / disabling.
1926 */
1927TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07001928 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001929 sp<FakeWindowHandle> window =
1930 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1931
1932 // Set focused application.
1933 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001934 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001935
1936 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00001937 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001938 setFocusedWindow(window);
1939
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001940 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1941
1942 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07001943 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001944 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001945 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
1946
1947 SCOPED_TRACE("Disable touch mode");
1948 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07001949 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001951 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001952 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
1953
1954 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07001955 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001956 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001957 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
1958
1959 SCOPED_TRACE("Enable touch mode again");
1960 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07001961 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00001962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001963 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001964 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1965
1966 window->assertNoEvents();
1967}
1968
Gang Wange9087892020-01-07 12:17:14 -05001969TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07001970 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05001971 sp<FakeWindowHandle> window =
1972 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
1973
1974 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07001975 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05001976
Arthur Hung72d8dc32020-03-28 00:48:39 +00001977 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001978 setFocusedWindow(window);
1979
Gang Wange9087892020-01-07 12:17:14 -05001980 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
1981
1982 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
1983 mDispatcher->notifyKey(&keyArgs);
1984
1985 InputEvent* event = window->consume();
1986 ASSERT_NE(event, nullptr);
1987
1988 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
1989 ASSERT_NE(verified, nullptr);
1990 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
1991
1992 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
1993 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
1994 ASSERT_EQ(keyArgs.source, verified->source);
1995 ASSERT_EQ(keyArgs.displayId, verified->displayId);
1996
1997 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
1998
1999 ASSERT_EQ(keyArgs.action, verifiedKey.action);
2000 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05002001 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
2002 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
2003 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
2004 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
2005 ASSERT_EQ(0, verifiedKey.repeatCount);
2006}
2007
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002008TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002010 sp<FakeWindowHandle> window =
2011 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2012
2013 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2014
Arthur Hung72d8dc32020-03-28 00:48:39 +00002015 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002016
2017 NotifyMotionArgs motionArgs =
2018 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2019 ADISPLAY_ID_DEFAULT);
2020 mDispatcher->notifyMotion(&motionArgs);
2021
2022 InputEvent* event = window->consume();
2023 ASSERT_NE(event, nullptr);
2024
2025 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2026 ASSERT_NE(verified, nullptr);
2027 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2028
2029 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2030 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2031 EXPECT_EQ(motionArgs.source, verified->source);
2032 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2033
2034 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2035
2036 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2037 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2038 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2039 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2040 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2041 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2042 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2043}
2044
chaviw09c8d2d2020-08-24 15:48:26 -07002045/**
2046 * Ensure that separate calls to sign the same data are generating the same key.
2047 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2048 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2049 * tests.
2050 */
2051TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2052 KeyEvent event = getTestKeyEvent();
2053 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2054
2055 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2056 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2057 ASSERT_EQ(hmac1, hmac2);
2058}
2059
2060/**
2061 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2062 */
2063TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2064 KeyEvent event = getTestKeyEvent();
2065 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2066 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2067
2068 verifiedEvent.deviceId += 1;
2069 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2070
2071 verifiedEvent.source += 1;
2072 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2073
2074 verifiedEvent.eventTimeNanos += 1;
2075 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2076
2077 verifiedEvent.displayId += 1;
2078 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2079
2080 verifiedEvent.action += 1;
2081 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2082
2083 verifiedEvent.downTimeNanos += 1;
2084 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2085
2086 verifiedEvent.flags += 1;
2087 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2088
2089 verifiedEvent.keyCode += 1;
2090 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2091
2092 verifiedEvent.scanCode += 1;
2093 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2094
2095 verifiedEvent.metaState += 1;
2096 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2097
2098 verifiedEvent.repeatCount += 1;
2099 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2100}
2101
Vishnu Nair958da932020-08-21 17:12:37 -07002102TEST_F(InputDispatcherTest, SetFocusedWindow) {
2103 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2104 sp<FakeWindowHandle> windowTop =
2105 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2106 sp<FakeWindowHandle> windowSecond =
2107 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2108 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2109
2110 // Top window is also focusable but is not granted focus.
2111 windowTop->setFocusable(true);
2112 windowSecond->setFocusable(true);
2113 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2114 setFocusedWindow(windowSecond);
2115
2116 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2118 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002119
2120 // Focused window should receive event.
2121 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2122 windowTop->assertNoEvents();
2123}
2124
2125TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2127 sp<FakeWindowHandle> window =
2128 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2129 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2130
2131 window->setFocusable(true);
2132 // Release channel for window is no longer valid.
2133 window->releaseChannel();
2134 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2135 setFocusedWindow(window);
2136
2137 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002138 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2139 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002140
2141 // window channel is invalid, so it should not receive any input event.
2142 window->assertNoEvents();
2143}
2144
2145TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2146 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2147 sp<FakeWindowHandle> window =
2148 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2149 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2150
2151 // Window is not focusable.
2152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2153 setFocusedWindow(window);
2154
2155 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002156 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2157 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002158
2159 // window is invalid, so it should not receive any input event.
2160 window->assertNoEvents();
2161}
2162
2163TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
2164 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2165 sp<FakeWindowHandle> windowTop =
2166 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2167 sp<FakeWindowHandle> windowSecond =
2168 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2169 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2170
2171 windowTop->setFocusable(true);
2172 windowSecond->setFocusable(true);
2173 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2174 setFocusedWindow(windowTop);
2175 windowTop->consumeFocusEvent(true);
2176
2177 setFocusedWindow(windowSecond, windowTop);
2178 windowSecond->consumeFocusEvent(true);
2179 windowTop->consumeFocusEvent(false);
2180
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2182 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002183
2184 // Focused window should receive event.
2185 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2186}
2187
2188TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
2189 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2190 sp<FakeWindowHandle> windowTop =
2191 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2192 sp<FakeWindowHandle> windowSecond =
2193 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2194 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2195
2196 windowTop->setFocusable(true);
2197 windowSecond->setFocusable(true);
2198 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2199 setFocusedWindow(windowSecond, windowTop);
2200
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002201 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2202 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002203
2204 // Event should be dropped.
2205 windowTop->assertNoEvents();
2206 windowSecond->assertNoEvents();
2207}
2208
2209TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
2210 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2211 sp<FakeWindowHandle> window =
2212 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2213 sp<FakeWindowHandle> previousFocusedWindow =
2214 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
2215 ADISPLAY_ID_DEFAULT);
2216 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2217
2218 window->setFocusable(true);
2219 previousFocusedWindow->setFocusable(true);
2220 window->setVisible(false);
2221 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
2222 setFocusedWindow(previousFocusedWindow);
2223 previousFocusedWindow->consumeFocusEvent(true);
2224
2225 // Requesting focus on invisible window takes focus from currently focused window.
2226 setFocusedWindow(window);
2227 previousFocusedWindow->consumeFocusEvent(false);
2228
2229 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07002231 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002232 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07002233
2234 // Window does not get focus event or key down.
2235 window->assertNoEvents();
2236
2237 // Window becomes visible.
2238 window->setVisible(true);
2239 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2240
2241 // Window receives focus event.
2242 window->consumeFocusEvent(true);
2243 // Focused window receives key down.
2244 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2245}
2246
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002247/**
2248 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
2249 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
2250 * of the 'slipperyEnterWindow'.
2251 *
2252 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
2253 * a way so that the touched location is no longer covered by the top window.
2254 *
2255 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
2256 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
2257 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
2258 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
2259 * with ACTION_DOWN).
2260 * Thus, the touch has been transferred from the top window into the bottom window, because the top
2261 * window moved itself away from the touched location and had Flag::SLIPPERY.
2262 *
2263 * Even though the top window moved away from the touched location, it is still obscuring the bottom
2264 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
2265 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
2266 *
2267 * In this test, we ensure that the event received by the bottom window has
2268 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
2269 */
2270TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
2271 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
2272 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
2273
2274 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2275 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2276
2277 sp<FakeWindowHandle> slipperyExitWindow =
2278 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2279 slipperyExitWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2280 InputWindowInfo::Flag::SLIPPERY);
2281 // Make sure this one overlaps the bottom window
2282 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
2283 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
2284 // one. Windows with the same owner are not considered to be occluding each other.
2285 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
2286
2287 sp<FakeWindowHandle> slipperyEnterWindow =
2288 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2289 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
2290
2291 mDispatcher->setInputWindows(
2292 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2293
2294 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
2295 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2296 ADISPLAY_ID_DEFAULT, {{50, 50}});
2297 mDispatcher->notifyMotion(&args);
2298 slipperyExitWindow->consumeMotionDown();
2299 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
2300 mDispatcher->setInputWindows(
2301 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2302
2303 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2304 ADISPLAY_ID_DEFAULT, {{51, 51}});
2305 mDispatcher->notifyMotion(&args);
2306
2307 slipperyExitWindow->consumeMotionCancel();
2308
2309 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
2310 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
2311}
2312
Garfield Tan1c7bc862020-01-28 13:24:04 -08002313class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2314protected:
2315 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2316 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2317
Chris Yea209fde2020-07-22 13:54:51 -07002318 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002319 sp<FakeWindowHandle> mWindow;
2320
2321 virtual void SetUp() override {
2322 mFakePolicy = new FakeInputDispatcherPolicy();
2323 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2324 mDispatcher = new InputDispatcher(mFakePolicy);
2325 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2326 ASSERT_EQ(OK, mDispatcher->start());
2327
2328 setUpWindow();
2329 }
2330
2331 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07002332 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08002333 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2334
Vishnu Nair47074b82020-08-14 11:54:47 -07002335 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002336 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002337 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002338 mWindow->consumeFocusEvent(true);
2339 }
2340
Chris Ye2ad95392020-09-01 13:44:44 -07002341 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002342 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002343 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002344 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2345 mDispatcher->notifyKey(&keyArgs);
2346
2347 // Window should receive key down event.
2348 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2349 }
2350
2351 void expectKeyRepeatOnce(int32_t repeatCount) {
2352 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2353 InputEvent* repeatEvent = mWindow->consume();
2354 ASSERT_NE(nullptr, repeatEvent);
2355
2356 uint32_t eventType = repeatEvent->getType();
2357 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2358
2359 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2360 uint32_t eventAction = repeatKeyEvent->getAction();
2361 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2362 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2363 }
2364
Chris Ye2ad95392020-09-01 13:44:44 -07002365 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002366 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002367 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002368 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2369 mDispatcher->notifyKey(&keyArgs);
2370
2371 // Window should receive key down event.
2372 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2373 0 /*expectedFlags*/);
2374 }
2375};
2376
2377TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07002378 sendAndConsumeKeyDown(1 /* deviceId */);
2379 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2380 expectKeyRepeatOnce(repeatCount);
2381 }
2382}
2383
2384TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
2385 sendAndConsumeKeyDown(1 /* deviceId */);
2386 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2387 expectKeyRepeatOnce(repeatCount);
2388 }
2389 sendAndConsumeKeyDown(2 /* deviceId */);
2390 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08002391 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2392 expectKeyRepeatOnce(repeatCount);
2393 }
2394}
2395
2396TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07002397 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002398 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07002399 sendAndConsumeKeyUp(1 /* deviceId */);
2400 mWindow->assertNoEvents();
2401}
2402
2403TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
2404 sendAndConsumeKeyDown(1 /* deviceId */);
2405 expectKeyRepeatOnce(1 /*repeatCount*/);
2406 sendAndConsumeKeyDown(2 /* deviceId */);
2407 expectKeyRepeatOnce(1 /*repeatCount*/);
2408 // Stale key up from device 1.
2409 sendAndConsumeKeyUp(1 /* deviceId */);
2410 // Device 2 is still down, keep repeating
2411 expectKeyRepeatOnce(2 /*repeatCount*/);
2412 expectKeyRepeatOnce(3 /*repeatCount*/);
2413 // Device 2 key up
2414 sendAndConsumeKeyUp(2 /* deviceId */);
2415 mWindow->assertNoEvents();
2416}
2417
2418TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
2419 sendAndConsumeKeyDown(1 /* deviceId */);
2420 expectKeyRepeatOnce(1 /*repeatCount*/);
2421 sendAndConsumeKeyDown(2 /* deviceId */);
2422 expectKeyRepeatOnce(1 /*repeatCount*/);
2423 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
2424 sendAndConsumeKeyUp(2 /* deviceId */);
2425 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08002426 mWindow->assertNoEvents();
2427}
2428
2429TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07002430 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002431 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2432 InputEvent* repeatEvent = mWindow->consume();
2433 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2434 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
2435 IdGenerator::getSource(repeatEvent->getId()));
2436 }
2437}
2438
2439TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07002440 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002441
2442 std::unordered_set<int32_t> idSet;
2443 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2444 InputEvent* repeatEvent = mWindow->consume();
2445 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
2446 int32_t id = repeatEvent->getId();
2447 EXPECT_EQ(idSet.end(), idSet.find(id));
2448 idSet.insert(id);
2449 }
2450}
2451
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002452/* Test InputDispatcher for MultiDisplay */
2453class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
2454public:
2455 static constexpr int32_t SECOND_DISPLAY_ID = 1;
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002456 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002457 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08002458
Chris Yea209fde2020-07-22 13:54:51 -07002459 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002460 windowInPrimary =
2461 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002462
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002463 // Set focus window for primary display, but focused display would be second one.
2464 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07002465 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002466 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002467 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002468 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08002469
Chris Yea209fde2020-07-22 13:54:51 -07002470 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002471 windowInSecondary =
2472 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002473 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002474 // Set focus display to second one.
2475 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
2476 // Set focus window for second display.
2477 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07002478 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002479 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002480 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002481 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002482 }
2483
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002484 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002485 InputDispatcherTest::TearDown();
2486
Chris Yea209fde2020-07-22 13:54:51 -07002487 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002488 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07002489 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002490 windowInSecondary.clear();
2491 }
2492
2493protected:
Chris Yea209fde2020-07-22 13:54:51 -07002494 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002495 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07002496 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002497 sp<FakeWindowHandle> windowInSecondary;
2498};
2499
2500TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
2501 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2503 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002505 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08002506 windowInSecondary->assertNoEvents();
2507
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002508 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2510 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2511 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002512 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002513 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08002514}
2515
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002516TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08002517 // Test inject a key down with display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2519 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002520 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08002521 windowInSecondary->assertNoEvents();
2522
2523 // Test inject a key down without display id specified.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2525 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08002526 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002527 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08002528
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002529 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002530 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08002531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002532 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002533 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
2534 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08002535
2536 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002537 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2538 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08002539 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002540 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08002541 windowInSecondary->assertNoEvents();
2542}
2543
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002544// Test per-display input monitors for motion event.
2545TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08002546 FakeMonitorReceiver monitorInPrimary =
2547 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2548 FakeMonitorReceiver monitorInSecondary =
2549 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002550
2551 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2553 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2554 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002555 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002556 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002557 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002558 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002559
2560 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2562 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
2563 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002564 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002565 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002566 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08002567 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002568
2569 // Test inject a non-pointer motion event.
2570 // If specific a display, it will dispatch to the focused window of particular display,
2571 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2573 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
2574 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002575 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002576 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002577 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002578 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002579}
2580
2581// Test per-display input monitors for key event.
2582TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002583 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08002584 FakeMonitorReceiver monitorInPrimary =
2585 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
2586 FakeMonitorReceiver monitorInSecondary =
2587 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002588
2589 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2591 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002592 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08002593 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002594 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08002595 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08002596}
2597
Vishnu Nair958da932020-08-21 17:12:37 -07002598TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
2599 sp<FakeWindowHandle> secondWindowInPrimary =
2600 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2601 secondWindowInPrimary->setFocusable(true);
2602 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
2603 setFocusedWindow(secondWindowInPrimary);
2604 windowInPrimary->consumeFocusEvent(false);
2605 secondWindowInPrimary->consumeFocusEvent(true);
2606
2607 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2609 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002610 windowInPrimary->assertNoEvents();
2611 windowInSecondary->assertNoEvents();
2612 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2613}
2614
Jackal Guof9696682018-10-05 12:23:23 +08002615class InputFilterTest : public InputDispatcherTest {
2616protected:
2617 static constexpr int32_t SECOND_DISPLAY_ID = 1;
2618
2619 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
2620 NotifyMotionArgs motionArgs;
2621
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002622 motionArgs =
2623 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002624 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002625 motionArgs =
2626 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08002627 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002628 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002629 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002630 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002631 } else {
2632 mFakePolicy->assertFilterInputEventWasNotCalled();
2633 }
2634 }
2635
2636 void testNotifyKey(bool expectToBeFiltered) {
2637 NotifyKeyArgs keyArgs;
2638
2639 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2640 mDispatcher->notifyKey(&keyArgs);
2641 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
2642 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002643 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08002644
2645 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08002646 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08002647 } else {
2648 mFakePolicy->assertFilterInputEventWasNotCalled();
2649 }
2650 }
2651};
2652
2653// Test InputFilter for MotionEvent
2654TEST_F(InputFilterTest, MotionEvent_InputFilter) {
2655 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
2656 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2657 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2658
2659 // Enable InputFilter
2660 mDispatcher->setInputFilterEnabled(true);
2661 // Test touch on both primary and second display, and check if both events are filtered.
2662 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
2663 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
2664
2665 // Disable InputFilter
2666 mDispatcher->setInputFilterEnabled(false);
2667 // Test touch on both primary and second display, and check if both events aren't filtered.
2668 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
2669 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
2670}
2671
2672// Test InputFilter for KeyEvent
2673TEST_F(InputFilterTest, KeyEvent_InputFilter) {
2674 // Since the InputFilter is disabled by default, check if key event aren't filtered.
2675 testNotifyKey(/*expectToBeFiltered*/ false);
2676
2677 // Enable InputFilter
2678 mDispatcher->setInputFilterEnabled(true);
2679 // Send a key event, and check if it is filtered.
2680 testNotifyKey(/*expectToBeFiltered*/ true);
2681
2682 // Disable InputFilter
2683 mDispatcher->setInputFilterEnabled(false);
2684 // Send a key event, and check if it isn't filtered.
2685 testNotifyKey(/*expectToBeFiltered*/ false);
2686}
2687
chaviwfd6d3512019-03-25 13:23:49 -07002688class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002689 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07002690 InputDispatcherTest::SetUp();
2691
Chris Yea209fde2020-07-22 13:54:51 -07002692 std::shared_ptr<FakeApplicationHandle> application =
2693 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002694 mUnfocusedWindow =
2695 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002696 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
2697 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2698 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002699 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002700
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002701 mFocusedWindow =
2702 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2703 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01002704 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07002705
2706 // Set focused application.
2707 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002708 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07002709
2710 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00002711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002712 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002713 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07002714 }
2715
Prabir Pradhan3608aad2019-10-02 17:08:26 -07002716 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07002717 InputDispatcherTest::TearDown();
2718
2719 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002720 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07002721 }
2722
2723protected:
2724 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002725 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002726 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07002727};
2728
2729// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2730// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
2731// the onPointerDownOutsideFocus callback.
2732TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002734 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2735 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002737 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002738
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002739 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07002740 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
2741}
2742
2743// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
2744// DOWN on the window that doesn't have focus. Ensure no window received the
2745// onPointerDownOutsideFocus callback.
2746TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002748 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002750 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002751
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002752 ASSERT_TRUE(mDispatcher->waitForIdle());
2753 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002754}
2755
2756// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
2757// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
2758TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2760 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002761 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07002762
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002763 ASSERT_TRUE(mDispatcher->waitForIdle());
2764 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002765}
2766
2767// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
2768// DOWN on the window that already has focus. Ensure no window received the
2769// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002770TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08002772 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07002773 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002774 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07002775 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07002776
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002777 ASSERT_TRUE(mDispatcher->waitForIdle());
2778 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07002779}
2780
chaviwaf87b3e2019-10-01 16:59:28 -07002781// These tests ensures we can send touch events to a single client when there are multiple input
2782// windows that point to the same client token.
2783class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
2784 virtual void SetUp() override {
2785 InputDispatcherTest::SetUp();
2786
Chris Yea209fde2020-07-22 13:54:51 -07002787 std::shared_ptr<FakeApplicationHandle> application =
2788 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07002789 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
2790 ADISPLAY_ID_DEFAULT);
2791 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
2792 // 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 +01002793 mWindow1->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2794 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002795 mWindow1->setFrame(Rect(0, 0, 100, 100));
2796
2797 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
2798 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Michael Wright44753b12020-07-08 13:48:11 +01002799 mWindow2->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
2800 InputWindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07002801 mWindow2->setFrame(Rect(100, 100, 200, 200));
2802
Arthur Hung72d8dc32020-03-28 00:48:39 +00002803 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07002804 }
2805
2806protected:
2807 sp<FakeWindowHandle> mWindow1;
2808 sp<FakeWindowHandle> mWindow2;
2809
2810 // Helper function to convert the point from screen coordinates into the window's space
2811 static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07002812 vec2 vals = windowInfo->transform.transform(point.x, point.y);
2813 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07002814 }
2815
2816 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
2817 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002818 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07002819 InputEvent* event = window->consume();
2820
2821 ASSERT_NE(nullptr, event) << name.c_str()
2822 << ": consumer should have returned non-NULL event.";
2823
2824 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
2825 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
2826 << " event, got " << inputEventTypeToString(event->getType()) << " event";
2827
2828 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
2829 EXPECT_EQ(expectedAction, motionEvent.getAction());
2830
2831 for (size_t i = 0; i < points.size(); i++) {
2832 float expectedX = points[i].x;
2833 float expectedY = points[i].y;
2834
2835 EXPECT_EQ(expectedX, motionEvent.getX(i))
2836 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
2837 << ", got " << motionEvent.getX(i);
2838 EXPECT_EQ(expectedY, motionEvent.getY(i))
2839 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
2840 << ", got " << motionEvent.getY(i);
2841 }
2842 }
chaviw9eaa22c2020-07-01 16:21:27 -07002843
2844 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
2845 std::vector<PointF> expectedPoints) {
2846 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
2847 ADISPLAY_ID_DEFAULT, touchedPoints);
2848 mDispatcher->notifyMotion(&motionArgs);
2849
2850 // Always consume from window1 since it's the window that has the InputReceiver
2851 consumeMotionEvent(mWindow1, action, expectedPoints);
2852 }
chaviwaf87b3e2019-10-01 16:59:28 -07002853};
2854
2855TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
2856 // Touch Window 1
2857 PointF touchedPoint = {10, 10};
2858 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002859 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002860
2861 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002862 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002863
2864 // Touch Window 2
2865 touchedPoint = {150, 150};
2866 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002867 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002868}
2869
chaviw9eaa22c2020-07-01 16:21:27 -07002870TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
2871 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07002872 mWindow2->setWindowScale(0.5f, 0.5f);
2873
2874 // Touch Window 1
2875 PointF touchedPoint = {10, 10};
2876 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002877 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002878 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07002879 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002880
2881 // Touch Window 2
2882 touchedPoint = {150, 150};
2883 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07002884 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
2885 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002886
chaviw9eaa22c2020-07-01 16:21:27 -07002887 // Update the transform so rotation is set
2888 mWindow2->setWindowTransform(0, -1, 1, 0);
2889 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
2890 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07002891}
2892
chaviw9eaa22c2020-07-01 16:21:27 -07002893TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002894 mWindow2->setWindowScale(0.5f, 0.5f);
2895
2896 // Touch Window 1
2897 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2898 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002899 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002900
2901 // Touch Window 2
2902 int32_t actionPointerDown =
2903 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002904 touchedPoints.push_back(PointF{150, 150});
2905 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2906 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002907
chaviw9eaa22c2020-07-01 16:21:27 -07002908 // Release Window 2
2909 int32_t actionPointerUp =
2910 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2911 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2912 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002913
chaviw9eaa22c2020-07-01 16:21:27 -07002914 // Update the transform so rotation is set for Window 2
2915 mWindow2->setWindowTransform(0, -1, 1, 0);
2916 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2917 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002918}
2919
chaviw9eaa22c2020-07-01 16:21:27 -07002920TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002921 mWindow2->setWindowScale(0.5f, 0.5f);
2922
2923 // Touch Window 1
2924 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2925 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002926 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002927
2928 // Touch Window 2
2929 int32_t actionPointerDown =
2930 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002931 touchedPoints.push_back(PointF{150, 150});
2932 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002933
chaviw9eaa22c2020-07-01 16:21:27 -07002934 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002935
2936 // Move both windows
2937 touchedPoints = {{20, 20}, {175, 175}};
2938 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2939 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2940
chaviw9eaa22c2020-07-01 16:21:27 -07002941 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002942
chaviw9eaa22c2020-07-01 16:21:27 -07002943 // Release Window 2
2944 int32_t actionPointerUp =
2945 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2946 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
2947 expectedPoints.pop_back();
2948
2949 // Touch Window 2
2950 mWindow2->setWindowTransform(0, -1, 1, 0);
2951 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
2952 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
2953
2954 // Move both windows
2955 touchedPoints = {{20, 20}, {175, 175}};
2956 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2957 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2958
2959 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002960}
2961
2962TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
2963 mWindow1->setWindowScale(0.5f, 0.5f);
2964
2965 // Touch Window 1
2966 std::vector<PointF> touchedPoints = {PointF{10, 10}};
2967 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07002968 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002969
2970 // Touch Window 2
2971 int32_t actionPointerDown =
2972 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07002973 touchedPoints.push_back(PointF{150, 150});
2974 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002975
chaviw9eaa22c2020-07-01 16:21:27 -07002976 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002977
2978 // Move both windows
2979 touchedPoints = {{20, 20}, {175, 175}};
2980 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
2981 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
2982
chaviw9eaa22c2020-07-01 16:21:27 -07002983 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00002984}
2985
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002986class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
2987 virtual void SetUp() override {
2988 InputDispatcherTest::SetUp();
2989
Chris Yea209fde2020-07-22 13:54:51 -07002990 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002991 mApplication->setDispatchingTimeout(20ms);
2992 mWindow =
2993 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2994 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05002995 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07002996 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002997 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
2998 // window.
Michael Wright44753b12020-07-08 13:48:11 +01002999 mWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003000
3001 // Set focused application.
3002 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
3003
3004 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003005 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003006 mWindow->consumeFocusEvent(true);
3007 }
3008
3009 virtual void TearDown() override {
3010 InputDispatcherTest::TearDown();
3011 mWindow.clear();
3012 }
3013
3014protected:
Chris Yea209fde2020-07-22 13:54:51 -07003015 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003016 sp<FakeWindowHandle> mWindow;
3017 static constexpr PointF WINDOW_LOCATION = {20, 20};
3018
3019 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003021 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3022 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003024 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3025 WINDOW_LOCATION));
3026 }
3027};
3028
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003029// Send a tap and respond, which should not cause an ANR.
3030TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
3031 tapOnWindow();
3032 mWindow->consumeMotionDown();
3033 mWindow->consumeMotionUp();
3034 ASSERT_TRUE(mDispatcher->waitForIdle());
3035 mFakePolicy->assertNotifyAnrWasNotCalled();
3036}
3037
3038// Send a regular key and respond, which should not cause an ANR.
3039TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003041 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
3042 ASSERT_TRUE(mDispatcher->waitForIdle());
3043 mFakePolicy->assertNotifyAnrWasNotCalled();
3044}
3045
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003046TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
3047 mWindow->setFocusable(false);
3048 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3049 mWindow->consumeFocusEvent(false);
3050
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003051 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003052 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003053 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003055 // Key will not go to window because we have no focused window.
3056 // The 'no focused window' ANR timer should start instead.
3057
3058 // Now, the focused application goes away.
3059 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
3060 // The key should get dropped and there should be no ANR.
3061
3062 ASSERT_TRUE(mDispatcher->waitForIdle());
3063 mFakePolicy->assertNotifyAnrWasNotCalled();
3064}
3065
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003066// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003067// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
3068// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003069TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003071 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3072 WINDOW_LOCATION));
3073
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003074 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
3075 ASSERT_TRUE(sequenceNum);
3076 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003077 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003078
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003079 mWindow->finishEvent(*sequenceNum);
3080 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3081 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003082 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003083 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003084}
3085
3086// Send a key to the app and have the app not respond right away.
3087TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
3088 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003090 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
3091 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003092 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003093 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003094 ASSERT_TRUE(mDispatcher->waitForIdle());
3095}
3096
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003097// We have a focused application, but no focused window
3098TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003099 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003100 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3101 mWindow->consumeFocusEvent(false);
3102
3103 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003105 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3106 WINDOW_LOCATION));
3107 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
3108 mDispatcher->waitForIdle();
3109 mFakePolicy->assertNotifyAnrWasNotCalled();
3110
3111 // Once a focused event arrives, we get an ANR for this application
3112 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3113 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003114 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003115 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003116 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3117 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003118 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003119 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003120 ASSERT_TRUE(mDispatcher->waitForIdle());
3121}
3122
3123// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003124// Make sure that we don't notify policy twice about the same ANR.
3125TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003126 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003127 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3128 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003129
3130 // Once a focused event arrives, we get an ANR for this application
3131 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3132 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003133 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003134 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003135 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3136 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003137 const std::chrono::duration appTimeout =
3138 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003139 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003140
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003141 std::this_thread::sleep_for(appTimeout);
3142 // ANR should not be raised again. It is up to policy to do that if it desires.
3143 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003144
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003145 // If we now get a focused window, the ANR should stop, but the policy handles that via
3146 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003147 ASSERT_TRUE(mDispatcher->waitForIdle());
3148}
3149
3150// We have a focused application, but no focused window
3151TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003152 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003153 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3154 mWindow->consumeFocusEvent(false);
3155
3156 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003157 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003158 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003159 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3160 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003161
3162 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003163 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003164
3165 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003166 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003167 ASSERT_TRUE(mDispatcher->waitForIdle());
3168 mWindow->assertNoEvents();
3169}
3170
3171/**
3172 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
3173 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
3174 * If we process 1 of the events, but ANR on the second event with the same timestamp,
3175 * the ANR mechanism should still work.
3176 *
3177 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
3178 * DOWN event, while not responding on the second one.
3179 */
3180TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
3181 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
3182 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3183 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3184 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3185 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003186 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003187
3188 // Now send ACTION_UP, with identical timestamp
3189 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3190 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3191 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3192 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003193 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003194
3195 // We have now sent down and up. Let's consume first event and then ANR on the second.
3196 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3197 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003198 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003199}
3200
3201// If an app is not responding to a key event, gesture monitors should continue to receive
3202// new motion events
3203TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
3204 FakeMonitorReceiver monitor =
3205 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3206 true /*isGestureMonitor*/);
3207
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3209 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003210 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003212
3213 // Stuck on the ACTION_UP
3214 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003215 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003216
3217 // New tap will go to the gesture monitor, but not to the window
3218 tapOnWindow();
3219 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3220 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3221
3222 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3223 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003224 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003225 mWindow->assertNoEvents();
3226 monitor.assertNoEvents();
3227}
3228
3229// If an app is not responding to a motion event, gesture monitors should continue to receive
3230// new motion events
3231TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
3232 FakeMonitorReceiver monitor =
3233 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3234 true /*isGestureMonitor*/);
3235
3236 tapOnWindow();
3237 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3238 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3239
3240 mWindow->consumeMotionDown();
3241 // Stuck on the ACTION_UP
3242 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003243 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003244
3245 // New tap will go to the gesture monitor, but not to the window
3246 tapOnWindow();
3247 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3248 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3249
3250 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3251 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003252 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003253 mWindow->assertNoEvents();
3254 monitor.assertNoEvents();
3255}
3256
3257// If a window is unresponsive, then you get anr. if the window later catches up and starts to
3258// process events, you don't get an anr. When the window later becomes unresponsive again, you
3259// get an ANR again.
3260// 1. tap -> block on ACTION_UP -> receive ANR
3261// 2. consume all pending events (= queue becomes healthy again)
3262// 3. tap again -> block on ACTION_UP again -> receive ANR second time
3263TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
3264 tapOnWindow();
3265
3266 mWindow->consumeMotionDown();
3267 // Block on ACTION_UP
3268 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003269 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003270 mWindow->consumeMotionUp(); // Now the connection should be healthy again
3271 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003272 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003273 mWindow->assertNoEvents();
3274
3275 tapOnWindow();
3276 mWindow->consumeMotionDown();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003277 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003278 mWindow->consumeMotionUp();
3279
3280 mDispatcher->waitForIdle();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003281 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
3282 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003283 mWindow->assertNoEvents();
3284}
3285
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003286// If a connection remains unresponsive for a while, make sure policy is only notified once about
3287// it.
3288TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003290 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3291 WINDOW_LOCATION));
3292
3293 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003294 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003295 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003296 // 'notifyConnectionUnresponsive' should only be called once per connection
3297 mFakePolicy->assertNotifyAnrWasNotCalled();
3298 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003299 mWindow->consumeMotionDown();
3300 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3301 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3302 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003303 mDispatcher->waitForIdle();
3304 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mWindow->getToken());
3305 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003306}
3307
3308/**
3309 * If a window is processing a motion event, and then a key event comes in, the key event should
3310 * not to to the focused window until the motion is processed.
3311 *
3312 * Warning!!!
3313 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3314 * and the injection timeout that we specify when injecting the key.
3315 * We must have the injection timeout (10ms) be smaller than
3316 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3317 *
3318 * If that value changes, this test should also change.
3319 */
3320TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
3321 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3322 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3323
3324 tapOnWindow();
3325 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3326 ASSERT_TRUE(downSequenceNum);
3327 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3328 ASSERT_TRUE(upSequenceNum);
3329 // Don't finish the events yet, and send a key
3330 // Injection will "succeed" because we will eventually give up and send the key to the focused
3331 // window even if motions are still being processed. But because the injection timeout is short,
3332 // we will receive INJECTION_TIMED_OUT as the result.
3333
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003334 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003335 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003336 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3337 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003338 // Key will not be sent to the window, yet, because the window is still processing events
3339 // and the key remains pending, waiting for the touch events to be processed
3340 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3341 ASSERT_FALSE(keySequenceNum);
3342
3343 std::this_thread::sleep_for(500ms);
3344 // if we wait long enough though, dispatcher will give up, and still send the key
3345 // to the focused window, even though we have not yet finished the motion event
3346 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3347 mWindow->finishEvent(*downSequenceNum);
3348 mWindow->finishEvent(*upSequenceNum);
3349}
3350
3351/**
3352 * If a window is processing a motion event, and then a key event comes in, the key event should
3353 * not go to the focused window until the motion is processed.
3354 * If then a new motion comes in, then the pending key event should be going to the currently
3355 * focused window right away.
3356 */
3357TEST_F(InputDispatcherSingleWindowAnr,
3358 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
3359 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
3360 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3361
3362 tapOnWindow();
3363 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
3364 ASSERT_TRUE(downSequenceNum);
3365 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
3366 ASSERT_TRUE(upSequenceNum);
3367 // Don't finish the events yet, and send a key
3368 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003369 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003370 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003371 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003372 // At this point, key is still pending, and should not be sent to the application yet.
3373 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
3374 ASSERT_FALSE(keySequenceNum);
3375
3376 // Now tap down again. It should cause the pending key to go to the focused window right away.
3377 tapOnWindow();
3378 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
3379 // the other events yet. We can finish events in any order.
3380 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
3381 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
3382 mWindow->consumeMotionDown();
3383 mWindow->consumeMotionUp();
3384 mWindow->assertNoEvents();
3385}
3386
3387class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
3388 virtual void SetUp() override {
3389 InputDispatcherTest::SetUp();
3390
Chris Yea209fde2020-07-22 13:54:51 -07003391 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003392 mApplication->setDispatchingTimeout(10ms);
3393 mUnfocusedWindow =
3394 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
3395 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3396 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3397 // window.
3398 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Michael Wright44753b12020-07-08 13:48:11 +01003399 mUnfocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3400 InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
3401 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003402
3403 mFocusedWindow =
3404 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003405 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003406 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Michael Wright44753b12020-07-08 13:48:11 +01003407 mFocusedWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
3408 InputWindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003409
3410 // Set focused application.
3411 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07003412 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003413
3414 // Expect one focus window exist in display.
3415 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003416 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003417 mFocusedWindow->consumeFocusEvent(true);
3418 }
3419
3420 virtual void TearDown() override {
3421 InputDispatcherTest::TearDown();
3422
3423 mUnfocusedWindow.clear();
3424 mFocusedWindow.clear();
3425 }
3426
3427protected:
Chris Yea209fde2020-07-22 13:54:51 -07003428 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003429 sp<FakeWindowHandle> mUnfocusedWindow;
3430 sp<FakeWindowHandle> mFocusedWindow;
3431 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
3432 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
3433 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
3434
3435 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
3436
3437 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
3438
3439private:
3440 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003442 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3443 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003445 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3446 location));
3447 }
3448};
3449
3450// If we have 2 windows that are both unresponsive, the one with the shortest timeout
3451// should be ANR'd first.
3452TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003454 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3455 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003456 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003457 mFocusedWindow->consumeMotionDown();
3458 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3459 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3460 // We consumed all events, so no ANR
3461 ASSERT_TRUE(mDispatcher->waitForIdle());
3462 mFakePolicy->assertNotifyAnrWasNotCalled();
3463
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003465 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3466 FOCUSED_WINDOW_LOCATION));
3467 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
3468 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003469
3470 const std::chrono::duration timeout =
3471 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003472 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
3473 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
3474 // sequence to make it consistent
3475 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003476 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003477 mFocusedWindow->consumeMotionDown();
3478 // This cancel is generated because the connection was unresponsive
3479 mFocusedWindow->consumeMotionCancel();
3480 mFocusedWindow->assertNoEvents();
3481 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003482 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003483 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
3484 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003485}
3486
3487// If we have 2 windows with identical timeouts that are both unresponsive,
3488// it doesn't matter which order they should have ANR.
3489// But we should receive ANR for both.
3490TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
3491 // Set the timeout for unfocused window to match the focused window
3492 mUnfocusedWindow->setDispatchingTimeout(10ms);
3493 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3494
3495 tapOnFocusedWindow();
3496 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003497 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveConnectionToken(10ms);
3498 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveConnectionToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003499
3500 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003501 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
3502 mFocusedWindow->getToken() == anrConnectionToken2);
3503 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
3504 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003505
3506 ASSERT_TRUE(mDispatcher->waitForIdle());
3507 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003508
3509 mFocusedWindow->consumeMotionDown();
3510 mFocusedWindow->consumeMotionUp();
3511 mUnfocusedWindow->consumeMotionOutside();
3512
3513 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveConnectionToken();
3514 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveConnectionToken();
3515
3516 // Both applications should be marked as responsive, in any order
3517 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
3518 mFocusedWindow->getToken() == responsiveToken2);
3519 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
3520 mUnfocusedWindow->getToken() == responsiveToken2);
3521 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003522}
3523
3524// If a window is already not responding, the second tap on the same window should be ignored.
3525// We should also log an error to account for the dropped event (not tested here).
3526// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
3527TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
3528 tapOnFocusedWindow();
3529 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3530 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3531 // Receive the events, but don't respond
3532 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
3533 ASSERT_TRUE(downEventSequenceNum);
3534 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
3535 ASSERT_TRUE(upEventSequenceNum);
3536 const std::chrono::duration timeout =
3537 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003538 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003539
3540 // Tap once again
3541 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003542 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003543 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3544 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003545 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003546 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3547 FOCUSED_WINDOW_LOCATION));
3548 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
3549 // valid touch target
3550 mUnfocusedWindow->assertNoEvents();
3551
3552 // Consume the first tap
3553 mFocusedWindow->finishEvent(*downEventSequenceNum);
3554 mFocusedWindow->finishEvent(*upEventSequenceNum);
3555 ASSERT_TRUE(mDispatcher->waitForIdle());
3556 // The second tap did not go to the focused window
3557 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003558 // Since all events are finished, connection should be deemed healthy again
3559 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003560 mFakePolicy->assertNotifyAnrWasNotCalled();
3561}
3562
3563// If you tap outside of all windows, there will not be ANR
3564TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003565 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003566 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3567 LOCATION_OUTSIDE_ALL_WINDOWS));
3568 ASSERT_TRUE(mDispatcher->waitForIdle());
3569 mFakePolicy->assertNotifyAnrWasNotCalled();
3570}
3571
3572// Since the focused window is paused, tapping on it should not produce any events
3573TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
3574 mFocusedWindow->setPaused(true);
3575 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
3576
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003577 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003578 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3579 FOCUSED_WINDOW_LOCATION));
3580
3581 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
3582 ASSERT_TRUE(mDispatcher->waitForIdle());
3583 // Should not ANR because the window is paused, and touches shouldn't go to it
3584 mFakePolicy->assertNotifyAnrWasNotCalled();
3585
3586 mFocusedWindow->assertNoEvents();
3587 mUnfocusedWindow->assertNoEvents();
3588}
3589
3590/**
3591 * If a window is processing a motion event, and then a key event comes in, the key event should
3592 * not to to the focused window until the motion is processed.
3593 * If a different window becomes focused at this time, the key should go to that window instead.
3594 *
3595 * Warning!!!
3596 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
3597 * and the injection timeout that we specify when injecting the key.
3598 * We must have the injection timeout (10ms) be smaller than
3599 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
3600 *
3601 * If that value changes, this test should also change.
3602 */
3603TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
3604 // Set a long ANR timeout to prevent it from triggering
3605 mFocusedWindow->setDispatchingTimeout(2s);
3606 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3607
3608 tapOnUnfocusedWindow();
3609 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
3610 ASSERT_TRUE(downSequenceNum);
3611 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
3612 ASSERT_TRUE(upSequenceNum);
3613 // Don't finish the events yet, and send a key
3614 // Injection will succeed because we will eventually give up and send the key to the focused
3615 // window even if motions are still being processed.
3616
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003617 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003618 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003619 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003621 // Key will not be sent to the window, yet, because the window is still processing events
3622 // and the key remains pending, waiting for the touch events to be processed
3623 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
3624 ASSERT_FALSE(keySequenceNum);
3625
3626 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07003627 mFocusedWindow->setFocusable(false);
3628 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003629 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003630 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003631
3632 // Focus events should precede the key events
3633 mUnfocusedWindow->consumeFocusEvent(true);
3634 mFocusedWindow->consumeFocusEvent(false);
3635
3636 // Finish the tap events, which should unblock dispatcher
3637 mUnfocusedWindow->finishEvent(*downSequenceNum);
3638 mUnfocusedWindow->finishEvent(*upSequenceNum);
3639
3640 // Now that all queues are cleared and no backlog in the connections, the key event
3641 // can finally go to the newly focused "mUnfocusedWindow".
3642 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3643 mFocusedWindow->assertNoEvents();
3644 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003645 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003646}
3647
3648// When the touch stream is split across 2 windows, and one of them does not respond,
3649// then ANR should be raised and the touch should be canceled for the unresponsive window.
3650// The other window should not be affected by that.
3651TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
3652 // Touch Window 1
3653 NotifyMotionArgs motionArgs =
3654 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3655 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
3656 mDispatcher->notifyMotion(&motionArgs);
3657 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
3658 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
3659
3660 // Touch Window 2
3661 int32_t actionPointerDown =
3662 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3663
3664 motionArgs =
3665 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3666 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
3667 mDispatcher->notifyMotion(&motionArgs);
3668
3669 const std::chrono::duration timeout =
3670 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003671 mFakePolicy->assertNotifyConnectionUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003672
3673 mUnfocusedWindow->consumeMotionDown();
3674 mFocusedWindow->consumeMotionDown();
3675 // Focused window may or may not receive ACTION_MOVE
3676 // But it should definitely receive ACTION_CANCEL due to the ANR
3677 InputEvent* event;
3678 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
3679 ASSERT_TRUE(moveOrCancelSequenceNum);
3680 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
3681 ASSERT_NE(nullptr, event);
3682 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
3683 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
3684 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
3685 mFocusedWindow->consumeMotionCancel();
3686 } else {
3687 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
3688 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003689 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003690 mFakePolicy->assertNotifyConnectionResponsiveWasCalled(mFocusedWindow->getToken());
3691
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003692 mUnfocusedWindow->assertNoEvents();
3693 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003694 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003695}
3696
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003697/**
3698 * If we have no focused window, and a key comes in, we start the ANR timer.
3699 * The focused application should add a focused window before the timer runs out to prevent ANR.
3700 *
3701 * If the user touches another application during this time, the key should be dropped.
3702 * Next, if a new focused window comes in, without toggling the focused application,
3703 * then no ANR should occur.
3704 *
3705 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
3706 * but in some cases the policy may not update the focused application.
3707 */
3708TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
3709 std::shared_ptr<FakeApplicationHandle> focusedApplication =
3710 std::make_shared<FakeApplicationHandle>();
3711 focusedApplication->setDispatchingTimeout(60ms);
3712 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
3713 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
3714 mFocusedWindow->setFocusable(false);
3715
3716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3717 mFocusedWindow->consumeFocusEvent(false);
3718
3719 // Send a key. The ANR timer should start because there is no focused window.
3720 // 'focusedApplication' will get blamed if this timer completes.
3721 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003722 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003723 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003724 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
3725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05003726
3727 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
3728 // then the injected touches won't cause the focused event to get dropped.
3729 // The dispatcher only checks for whether the queue should be pruned upon queueing.
3730 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
3731 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
3732 // For this test, it means that the key would get delivered to the window once it becomes
3733 // focused.
3734 std::this_thread::sleep_for(10ms);
3735
3736 // Touch unfocused window. This should force the pending key to get dropped.
3737 NotifyMotionArgs motionArgs =
3738 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3739 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
3740 mDispatcher->notifyMotion(&motionArgs);
3741
3742 // We do not consume the motion right away, because that would require dispatcher to first
3743 // process (== drop) the key event, and by that time, ANR will be raised.
3744 // Set the focused window first.
3745 mFocusedWindow->setFocusable(true);
3746 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
3747 setFocusedWindow(mFocusedWindow);
3748 mFocusedWindow->consumeFocusEvent(true);
3749 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
3750 // to another application. This could be a bug / behaviour in the policy.
3751
3752 mUnfocusedWindow->consumeMotionDown();
3753
3754 ASSERT_TRUE(mDispatcher->waitForIdle());
3755 // Should not ANR because we actually have a focused window. It was just added too slowly.
3756 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
3757}
3758
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05003759// These tests ensure we cannot send touch events to a window that's positioned behind a window
3760// that has feature NO_INPUT_CHANNEL.
3761// Layout:
3762// Top (closest to user)
3763// mNoInputWindow (above all windows)
3764// mBottomWindow
3765// Bottom (furthest from user)
3766class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
3767 virtual void SetUp() override {
3768 InputDispatcherTest::SetUp();
3769
3770 mApplication = std::make_shared<FakeApplicationHandle>();
3771 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3772 "Window without input channel", ADISPLAY_ID_DEFAULT,
3773 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
3774
3775 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3776 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3777 // It's perfectly valid for this window to not have an associated input channel
3778
3779 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
3780 ADISPLAY_ID_DEFAULT);
3781 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
3782
3783 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3784 }
3785
3786protected:
3787 std::shared_ptr<FakeApplicationHandle> mApplication;
3788 sp<FakeWindowHandle> mNoInputWindow;
3789 sp<FakeWindowHandle> mBottomWindow;
3790};
3791
3792TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
3793 PointF touchedPoint = {10, 10};
3794
3795 NotifyMotionArgs motionArgs =
3796 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3797 ADISPLAY_ID_DEFAULT, {touchedPoint});
3798 mDispatcher->notifyMotion(&motionArgs);
3799
3800 mNoInputWindow->assertNoEvents();
3801 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
3802 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
3803 // and therefore should prevent mBottomWindow from receiving touches
3804 mBottomWindow->assertNoEvents();
3805}
3806
3807/**
3808 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
3809 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
3810 */
3811TEST_F(InputDispatcherMultiWindowOcclusionTests,
3812 NoInputChannelFeature_DropsTouchesWithValidChannel) {
3813 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
3814 "Window with input channel and NO_INPUT_CHANNEL",
3815 ADISPLAY_ID_DEFAULT);
3816
3817 mNoInputWindow->setInputFeatures(InputWindowInfo::Feature::NO_INPUT_CHANNEL);
3818 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
3819 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
3820
3821 PointF touchedPoint = {10, 10};
3822
3823 NotifyMotionArgs motionArgs =
3824 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3825 ADISPLAY_ID_DEFAULT, {touchedPoint});
3826 mDispatcher->notifyMotion(&motionArgs);
3827
3828 mNoInputWindow->assertNoEvents();
3829 mBottomWindow->assertNoEvents();
3830}
3831
Vishnu Nair958da932020-08-21 17:12:37 -07003832class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
3833protected:
3834 std::shared_ptr<FakeApplicationHandle> mApp;
3835 sp<FakeWindowHandle> mWindow;
3836 sp<FakeWindowHandle> mMirror;
3837
3838 virtual void SetUp() override {
3839 InputDispatcherTest::SetUp();
3840 mApp = std::make_shared<FakeApplicationHandle>();
3841 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3842 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
3843 mWindow->getToken());
3844 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
3845 mWindow->setFocusable(true);
3846 mMirror->setFocusable(true);
3847 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3848 }
3849};
3850
3851TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
3852 // Request focus on a mirrored window
3853 setFocusedWindow(mMirror);
3854
3855 // window gets focused
3856 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3858 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003859 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
3860}
3861
3862// A focused & mirrored window remains focused only if the window and its mirror are both
3863// focusable.
3864TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
3865 setFocusedWindow(mMirror);
3866
3867 // window gets focused
3868 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3870 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003871 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3873 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003874 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3875
3876 mMirror->setFocusable(false);
3877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3878
3879 // window loses focus since one of the windows associated with the token in not focusable
3880 mWindow->consumeFocusEvent(false);
3881
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003882 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3883 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003884 mWindow->assertNoEvents();
3885}
3886
3887// A focused & mirrored window remains focused until the window and its mirror both become
3888// invisible.
3889TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
3890 setFocusedWindow(mMirror);
3891
3892 // window gets focused
3893 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3895 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003896 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3898 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003899 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3900
3901 mMirror->setVisible(false);
3902 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3903
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3905 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003906 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3908 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003909 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3910
3911 mWindow->setVisible(false);
3912 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3913
3914 // window loses focus only after all windows associated with the token become invisible.
3915 mWindow->consumeFocusEvent(false);
3916
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003917 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3918 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003919 mWindow->assertNoEvents();
3920}
3921
3922// A focused & mirrored window remains focused until both windows are removed.
3923TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
3924 setFocusedWindow(mMirror);
3925
3926 // window gets focused
3927 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3929 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003930 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3932 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003933 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3934
3935 // single window is removed but the window token remains focused
3936 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
3937
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3939 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003940 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
3942 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003943 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
3944
3945 // Both windows are removed
3946 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3947 mWindow->consumeFocusEvent(false);
3948
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003949 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3950 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003951 mWindow->assertNoEvents();
3952}
3953
3954// Focus request can be pending until one window becomes visible.
3955TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
3956 // Request focus on an invisible mirror.
3957 mWindow->setVisible(false);
3958 mMirror->setVisible(false);
3959 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3960 setFocusedWindow(mMirror);
3961
3962 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003964 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003965 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003966
3967 mMirror->setVisible(true);
3968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
3969
3970 // window gets focused
3971 mWindow->consumeFocusEvent(true);
3972 // window gets the pending key event
3973 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3974}
Prabir Pradhan99987712020-11-10 18:43:05 -08003975
3976class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
3977protected:
3978 std::shared_ptr<FakeApplicationHandle> mApp;
3979 sp<FakeWindowHandle> mWindow;
3980 sp<FakeWindowHandle> mSecondWindow;
3981
3982 void SetUp() override {
3983 InputDispatcherTest::SetUp();
3984 mApp = std::make_shared<FakeApplicationHandle>();
3985 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3986 mWindow->setFocusable(true);
3987 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
3988 mSecondWindow->setFocusable(true);
3989
3990 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
3991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
3992
3993 setFocusedWindow(mWindow);
3994 mWindow->consumeFocusEvent(true);
3995 }
3996
3997 void notifyPointerCaptureChanged(bool enabled) {
3998 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(enabled);
3999 mDispatcher->notifyPointerCaptureChanged(&args);
4000 }
4001
4002 void requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window, bool enabled) {
4003 mDispatcher->requestPointerCapture(window->getToken(), enabled);
4004 mFakePolicy->waitForSetPointerCapture(enabled);
4005 notifyPointerCaptureChanged(enabled);
4006 window->consumeCaptureEvent(enabled);
4007 }
4008};
4009
4010TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
4011 // Ensure that capture cannot be obtained for unfocused windows.
4012 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
4013 mFakePolicy->assertSetPointerCaptureNotCalled();
4014 mSecondWindow->assertNoEvents();
4015
4016 // Ensure that capture can be enabled from the focus window.
4017 requestAndVerifyPointerCapture(mWindow, true);
4018
4019 // Ensure that capture cannot be disabled from a window that does not have capture.
4020 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
4021 mFakePolicy->assertSetPointerCaptureNotCalled();
4022
4023 // Ensure that capture can be disabled from the window with capture.
4024 requestAndVerifyPointerCapture(mWindow, false);
4025}
4026
4027TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
4028 requestAndVerifyPointerCapture(mWindow, true);
4029
4030 setFocusedWindow(mSecondWindow);
4031
4032 // Ensure that the capture disabled event was sent first.
4033 mWindow->consumeCaptureEvent(false);
4034 mWindow->consumeFocusEvent(false);
4035 mSecondWindow->consumeFocusEvent(true);
4036 mFakePolicy->waitForSetPointerCapture(false);
4037
4038 // Ensure that additional state changes from InputReader are not sent to the window.
4039 notifyPointerCaptureChanged(false);
4040 notifyPointerCaptureChanged(true);
4041 notifyPointerCaptureChanged(false);
4042 mWindow->assertNoEvents();
4043 mSecondWindow->assertNoEvents();
4044 mFakePolicy->assertSetPointerCaptureNotCalled();
4045}
4046
4047TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
4048 requestAndVerifyPointerCapture(mWindow, true);
4049
4050 // InputReader unexpectedly disables and enables pointer capture.
4051 notifyPointerCaptureChanged(false);
4052 notifyPointerCaptureChanged(true);
4053
4054 // Ensure that Pointer Capture is disabled.
4055 mWindow->consumeCaptureEvent(false);
4056 mWindow->assertNoEvents();
4057}
4058
Garfield Tane84e6f92019-08-29 17:28:41 -07004059} // namespace android::inputdispatcher