blob: e9d45b22ad17ff2711b8862295cd079a4da68720 [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
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070019#include <android-base/properties.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080020#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070021#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070022#include <binder/Binder.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080023#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100024#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080025#include <linux/input.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100026
Garfield Tan1c7bc862020-01-28 13:24:04 -080027#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070028#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080029#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080030#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080031
Garfield Tan1c7bc862020-01-28 13:24:04 -080032using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050033using android::gui::FocusRequest;
34using android::gui::TouchOcclusionMode;
35using android::gui::WindowInfo;
36using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080037using android::os::InputEventInjectionResult;
38using android::os::InputEventInjectionSync;
Michael Wright44753b12020-07-08 13:48:11 +010039using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080040
Garfield Tane84e6f92019-08-29 17:28:41 -070041namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080042
43// An arbitrary time value.
44static const nsecs_t ARBITRARY_TIME = 1234;
45
46// An arbitrary device id.
47static const int32_t DEVICE_ID = 1;
48
Jeff Brownf086ddb2014-02-11 14:28:48 -080049// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000050static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
51static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080052
Michael Wrightd02c5b62014-02-10 15:10:22 -080053// An arbitrary injector pid / uid pair that has permission to inject events.
54static const int32_t INJECTOR_PID = 999;
55static const int32_t INJECTOR_UID = 1001;
56
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000057// An arbitrary pid of the gesture monitor window
58static constexpr int32_t MONITOR_PID = 2001;
59
chaviwd1c23182019-12-20 18:44:56 -080060struct PointF {
61 float x;
62 float y;
63};
Michael Wrightd02c5b62014-02-10 15:10:22 -080064
Gang Wang342c9272020-01-13 13:15:04 -050065/**
66 * Return a DOWN key event with KEYCODE_A.
67 */
68static KeyEvent getTestKeyEvent() {
69 KeyEvent event;
70
Garfield Tanfbe732e2020-01-24 11:26:14 -080071 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
72 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
73 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050074 return event;
75}
76
Siarhei Vishniakouca205502021-07-16 21:31:58 +000077static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
78 ASSERT_EQ(expectedAction, receivedAction)
79 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
80 << MotionEvent::actionToString(receivedAction);
81}
82
Michael Wrightd02c5b62014-02-10 15:10:22 -080083// --- FakeInputDispatcherPolicy ---
84
85class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
86 InputDispatcherConfiguration mConfig;
87
88protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100089 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080090
91public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100092 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080093
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080094 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080095 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
96 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080097 }
98
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080099 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800100 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
101 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +0800102 }
103
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700104 void assertFilterInputEventWasNotCalled() {
105 std::scoped_lock lock(mLock);
106 ASSERT_EQ(nullptr, mFilteredEvent);
107 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800108
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800109 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700110 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800111 ASSERT_TRUE(mConfigurationChangedTime)
112 << "Timed out waiting for configuration changed call";
113 ASSERT_EQ(*mConfigurationChangedTime, when);
114 mConfigurationChangedTime = std::nullopt;
115 }
116
117 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700118 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800119 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800120 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800121 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
122 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
123 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
124 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
125 mLastNotifySwitch = std::nullopt;
126 }
127
chaviwfd6d3512019-03-25 13:23:49 -0700128 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700129 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800130 ASSERT_EQ(touchedToken, mOnPointerDownToken);
131 mOnPointerDownToken.clear();
132 }
133
134 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700135 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800136 ASSERT_TRUE(mOnPointerDownToken == nullptr)
137 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700138 }
139
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700140 // This function must be called soon after the expected ANR timer starts,
141 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500142 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700143 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500144 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
145 std::shared_ptr<InputApplicationHandle> application;
146 { // acquire lock
147 std::unique_lock lock(mLock);
148 android::base::ScopedLockAssertion assumeLocked(mLock);
149 ASSERT_NO_FATAL_FAILURE(
150 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
151 } // release lock
152 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700153 }
154
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000155 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
156 const sp<IBinder>& expectedConnectionToken) {
157 sp<IBinder> connectionToken = getUnresponsiveWindowToken(timeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500158 ASSERT_EQ(expectedConnectionToken, connectionToken);
159 }
160
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000161 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
162 sp<IBinder> connectionToken = getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500163 ASSERT_EQ(expectedConnectionToken, connectionToken);
164 }
165
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000166 void assertNotifyMonitorUnresponsiveWasCalled(std::chrono::nanoseconds timeout) {
167 int32_t pid = getUnresponsiveMonitorPid(timeout);
168 ASSERT_EQ(MONITOR_PID, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500169 }
170
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000171 void assertNotifyMonitorResponsiveWasCalled() {
172 int32_t pid = getResponsiveMonitorPid();
173 ASSERT_EQ(MONITOR_PID, pid);
174 }
175
176 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500177 std::unique_lock lock(mLock);
178 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000179 return getAnrTokenLockedInterruptible(timeout, mAnrWindowTokens, lock);
180 }
181
182 sp<IBinder> getResponsiveWindowToken() {
183 std::unique_lock lock(mLock);
184 android::base::ScopedLockAssertion assumeLocked(mLock);
185 return getAnrTokenLockedInterruptible(0s, mResponsiveWindowTokens, lock);
186 }
187
188 int32_t getUnresponsiveMonitorPid(std::chrono::nanoseconds timeout) {
189 std::unique_lock lock(mLock);
190 android::base::ScopedLockAssertion assumeLocked(mLock);
191 return getAnrTokenLockedInterruptible(timeout, mAnrMonitorPids, lock);
192 }
193
194 int32_t getResponsiveMonitorPid() {
195 std::unique_lock lock(mLock);
196 android::base::ScopedLockAssertion assumeLocked(mLock);
197 return getAnrTokenLockedInterruptible(0s, mResponsiveMonitorPids, lock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500198 }
199
200 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
201 // for a specific container to become non-empty. When the container is non-empty, return the
202 // first entry from the container and erase it.
203 template <class T>
204 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
205 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
206 const std::chrono::time_point start = std::chrono::steady_clock::now();
207 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700208
209 // If there is an ANR, Dispatcher won't be idle because there are still events
210 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
211 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500212 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
213 // to provide it some time to act. 100ms seems reasonable.
214 mNotifyAnr.wait_for(lock, timeToWait,
215 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700216 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500217 if (storage.empty()) {
218 ADD_FAILURE() << "Did not receive the ANR callback";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000219 return {};
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700220 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700221 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
222 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700223 if (std::chrono::abs(timeout - waited) > 100ms) {
224 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
225 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
226 << "ms, but waited "
227 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
228 << "ms instead";
229 }
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 T token = storage.front();
231 storage.pop();
232 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700233 }
234
235 void assertNotifyAnrWasNotCalled() {
236 std::scoped_lock lock(mLock);
237 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000238 ASSERT_TRUE(mAnrWindowTokens.empty());
239 ASSERT_TRUE(mAnrMonitorPids.empty());
240 ASSERT_TRUE(mResponsiveWindowTokens.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500241 << "ANR was not called, but please also consume the 'connection is responsive' "
242 "signal";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000243 ASSERT_TRUE(mResponsiveMonitorPids.empty())
244 << "Monitor ANR was not called, but please also consume the 'monitor is responsive'"
245 " signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700246 }
247
Garfield Tan1c7bc862020-01-28 13:24:04 -0800248 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
249 mConfig.keyRepeatTimeout = timeout;
250 mConfig.keyRepeatDelay = delay;
251 }
252
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000253 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800254 std::unique_lock lock(mLock);
255 base::ScopedLockAssertion assumeLocked(mLock);
256
257 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
258 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000259 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800260 enabled;
261 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000262 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
263 << ") to be called.";
264 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800265 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000266 auto request = *mPointerCaptureRequest;
267 mPointerCaptureRequest.reset();
268 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800269 }
270
271 void assertSetPointerCaptureNotCalled() {
272 std::unique_lock lock(mLock);
273 base::ScopedLockAssertion assumeLocked(mLock);
274
275 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000276 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800277 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000278 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800279 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000280 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800281 }
282
arthurhungf452d0b2021-01-06 00:19:52 +0800283 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
284 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800285 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800286 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800287 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800288 }
289
Michael Wrightd02c5b62014-02-10 15:10:22 -0800290private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700291 std::mutex mLock;
292 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
293 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
294 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
295 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800296
Prabir Pradhan99987712020-11-10 18:43:05 -0800297 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000298
299 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800300
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700301 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700302 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000303 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
304 std::queue<sp<IBinder>> mResponsiveWindowTokens GUARDED_BY(mLock);
305 std::queue<int32_t> mAnrMonitorPids GUARDED_BY(mLock);
306 std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700307 std::condition_variable mNotifyAnr;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700308
arthurhungf452d0b2021-01-06 00:19:52 +0800309 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800310 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800311
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600312 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700313 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800314 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800315 }
316
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000317 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700318 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000319 mAnrWindowTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700320 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500321 }
322
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000323 void notifyMonitorUnresponsive(int32_t pid, const std::string&) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500324 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000325 mAnrMonitorPids.push(pid);
326 mNotifyAnr.notify_all();
327 }
328
329 void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {
330 std::scoped_lock lock(mLock);
331 mResponsiveWindowTokens.push(connectionToken);
332 mNotifyAnr.notify_all();
333 }
334
335 void notifyMonitorResponsive(int32_t pid) override {
336 std::scoped_lock lock(mLock);
337 mResponsiveMonitorPids.push(pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500338 mNotifyAnr.notify_all();
339 }
340
341 void notifyNoFocusedWindowAnr(
342 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
343 std::scoped_lock lock(mLock);
344 mAnrApplications.push(applicationHandle);
345 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800346 }
347
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600348 void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600350 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700351
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600352 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Chris Yef59a2f42020-10-16 12:55:26 -0700353 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
354 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
355 const std::vector<float>& values) override {}
356
357 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
358 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000359
Chris Yefb552902021-02-03 17:18:37 -0800360 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
361
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600362 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800363 *outConfig = mConfig;
364 }
365
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600366 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700367 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800368 switch (inputEvent->getType()) {
369 case AINPUT_EVENT_TYPE_KEY: {
370 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800371 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800372 break;
373 }
374
375 case AINPUT_EVENT_TYPE_MOTION: {
376 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800377 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800378 break;
379 }
380 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800381 return true;
382 }
383
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600384 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800385
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600386 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800387
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600388 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800389 return 0;
390 }
391
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600392 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800393 return false;
394 }
395
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600396 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
397 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700398 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800399 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
400 * essentially a passthrough for notifySwitch.
401 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800402 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800403 }
404
Sean Stoutb4e0a592021-02-23 07:34:53 -0800405 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800406
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800407 bool checkInjectEventsPermissionNonReentrant(int32_t pid, int32_t uid) override {
408 return pid == INJECTOR_PID && uid == INJECTOR_UID;
409 }
Jackal Guof9696682018-10-05 12:23:23 +0800410
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600411 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700412 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700413 mOnPointerDownToken = newToken;
414 }
415
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000416 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800417 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000418 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800419 mPointerCaptureChangedCondition.notify_all();
420 }
421
arthurhungf452d0b2021-01-06 00:19:52 +0800422 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
423 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800424 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800425 mDropTargetWindowToken = token;
426 }
427
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800428 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
429 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700430 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800431 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
432 ASSERT_EQ(mFilteredEvent->getType(), type);
433
434 if (type == AINPUT_EVENT_TYPE_KEY) {
435 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
436 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
437 EXPECT_EQ(keyEvent.getAction(), action);
438 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
439 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
440 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
441 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
442 EXPECT_EQ(motionEvent.getAction(), action);
443 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
444 } else {
445 FAIL() << "Unknown type: " << type;
446 }
447
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800448 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800449 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800450};
451
Michael Wrightd02c5b62014-02-10 15:10:22 -0800452// --- InputDispatcherTest ---
453
454class InputDispatcherTest : public testing::Test {
455protected:
456 sp<FakeInputDispatcherPolicy> mFakePolicy;
457 sp<InputDispatcher> mDispatcher;
458
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000459 void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800460 mFakePolicy = new FakeInputDispatcherPolicy();
461 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800462 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000463 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700464 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800465 }
466
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000467 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700468 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800469 mFakePolicy.clear();
470 mDispatcher.clear();
471 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700472
473 /**
474 * Used for debugging when writing the test
475 */
476 void dumpDispatcherState() {
477 std::string dump;
478 mDispatcher->dump(dump);
479 std::stringstream ss(dump);
480 std::string to;
481
482 while (std::getline(ss, to, '\n')) {
483 ALOGE("%s", to.c_str());
484 }
485 }
Vishnu Nair958da932020-08-21 17:12:37 -0700486
chaviw3277faf2021-05-19 16:45:23 -0500487 void setFocusedWindow(const sp<WindowInfoHandle>& window,
488 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700489 FocusRequest request;
490 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000491 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700492 if (focusedWindow) {
493 request.focusedToken = focusedWindow->getToken();
494 }
495 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
496 request.displayId = window->getInfo()->displayId;
497 mDispatcher->setFocusedWindow(request);
498 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800499};
500
Michael Wrightd02c5b62014-02-10 15:10:22 -0800501TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
502 KeyEvent event;
503
504 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800505 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
506 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600507 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
508 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800509 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700510 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800511 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800512 << "Should reject key events with undefined action.";
513
514 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800515 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
516 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600517 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800518 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700519 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800520 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800521 << "Should reject key events with ACTION_MULTIPLE.";
522}
523
524TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
525 MotionEvent event;
526 PointerProperties pointerProperties[MAX_POINTERS + 1];
527 PointerCoords pointerCoords[MAX_POINTERS + 1];
528 for (int i = 0; i <= MAX_POINTERS; i++) {
529 pointerProperties[i].clear();
530 pointerProperties[i].id = i;
531 pointerCoords[i].clear();
532 }
533
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800534 // Some constants commonly used below
535 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
536 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
537 constexpr int32_t metaState = AMETA_NONE;
538 constexpr MotionClassification classification = MotionClassification::NONE;
539
chaviw9eaa22c2020-07-01 16:21:27 -0700540 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800541 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800542 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700543 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
544 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700545 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
546 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700547 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800548 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700549 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800550 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551 << "Should reject motion events with undefined action.";
552
553 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800554 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700555 AMOTION_EVENT_ACTION_POINTER_DOWN |
556 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700557 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
558 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700559 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500560 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800561 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700562 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800563 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800564 << "Should reject motion events with pointer down index too large.";
565
Garfield Tanfbe732e2020-01-24 11:26:14 -0800566 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700567 AMOTION_EVENT_ACTION_POINTER_DOWN |
568 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700569 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
570 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700571 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500572 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800573 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700574 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800575 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576 << "Should reject motion events with pointer down index too small.";
577
578 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800579 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700580 AMOTION_EVENT_ACTION_POINTER_UP |
581 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700582 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
583 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700584 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500585 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800586 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700587 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800588 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800589 << "Should reject motion events with pointer up index too large.";
590
Garfield Tanfbe732e2020-01-24 11:26:14 -0800591 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700592 AMOTION_EVENT_ACTION_POINTER_UP |
593 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700594 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
595 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700596 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500597 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800598 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700599 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800600 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800601 << "Should reject motion events with pointer up index too small.";
602
603 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800604 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
605 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700606 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700607 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
608 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700609 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800610 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700611 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800612 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800613 << "Should reject motion events with 0 pointers.";
614
Garfield Tanfbe732e2020-01-24 11:26:14 -0800615 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
616 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700617 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700618 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
619 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700620 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800621 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700622 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800623 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800624 << "Should reject motion events with more than MAX_POINTERS pointers.";
625
626 // Rejects motion events with invalid pointer ids.
627 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800628 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
629 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700630 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700631 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
632 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700633 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800634 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700635 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800636 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800637 << "Should reject motion events with pointer ids less than 0.";
638
639 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800640 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
641 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700642 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700643 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
644 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700645 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800646 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700647 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800648 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800649 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
650
651 // Rejects motion events with duplicate pointer ids.
652 pointerProperties[0].id = 1;
653 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800654 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
655 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700656 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700657 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
658 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700659 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800660 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700661 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800662 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663 << "Should reject motion events with duplicate pointer ids.";
664}
665
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800666/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
667
668TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
669 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800670 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800671 mDispatcher->notifyConfigurationChanged(&args);
672 ASSERT_TRUE(mDispatcher->waitForIdle());
673
674 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
675}
676
677TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800678 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
679 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800680 mDispatcher->notifySwitch(&args);
681
682 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
683 args.policyFlags |= POLICY_FLAG_TRUSTED;
684 mFakePolicy->assertNotifySwitchWasCalled(args);
685}
686
Arthur Hungb92218b2018-08-14 12:00:21 +0800687// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700688static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700689// Default input dispatching timeout if there is no focused application or paused window
690// from which to determine an appropriate dispatching timeout.
691static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
692 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
693 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800694
695class FakeApplicationHandle : public InputApplicationHandle {
696public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700697 FakeApplicationHandle() {
698 mInfo.name = "Fake Application";
699 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500700 mInfo.dispatchingTimeoutMillis =
701 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700702 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800703 virtual ~FakeApplicationHandle() {}
704
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000705 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700706
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500707 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
708 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700709 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800710};
711
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800712class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800713public:
Garfield Tan15601662020-09-22 15:32:38 -0700714 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800715 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700716 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800717 }
718
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800719 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700720 InputEvent* event;
721 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
722 if (!consumeSeq) {
723 return nullptr;
724 }
725 finishEvent(*consumeSeq);
726 return event;
727 }
728
729 /**
730 * Receive an event without acknowledging it.
731 * Return the sequence number that could later be used to send finished signal.
732 */
733 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800734 uint32_t consumeSeq;
735 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800736
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800737 std::chrono::time_point start = std::chrono::steady_clock::now();
738 status_t status = WOULD_BLOCK;
739 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800740 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800741 &event);
742 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
743 if (elapsed > 100ms) {
744 break;
745 }
746 }
747
748 if (status == WOULD_BLOCK) {
749 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700750 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800751 }
752
753 if (status != OK) {
754 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700755 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800756 }
757 if (event == nullptr) {
758 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700759 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800760 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700761 if (outEvent != nullptr) {
762 *outEvent = event;
763 }
764 return consumeSeq;
765 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800766
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700767 /**
768 * To be used together with "receiveEvent" to complete the consumption of an event.
769 */
770 void finishEvent(uint32_t consumeSeq) {
771 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
772 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800773 }
774
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000775 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
776 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
777 ASSERT_EQ(OK, status);
778 }
779
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000780 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
781 std::optional<int32_t> expectedDisplayId,
782 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800783 InputEvent* event = consume();
784
785 ASSERT_NE(nullptr, event) << mName.c_str()
786 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800787 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700788 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800789 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800790
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000791 if (expectedDisplayId.has_value()) {
792 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
793 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800794
Tiger Huang8664f8c2018-10-11 19:14:35 +0800795 switch (expectedEventType) {
796 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800797 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
798 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000799 if (expectedFlags.has_value()) {
800 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
801 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800802 break;
803 }
804 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800805 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000806 assertMotionAction(expectedAction, motionEvent.getAction());
807
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000808 if (expectedFlags.has_value()) {
809 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
810 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800811 break;
812 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100813 case AINPUT_EVENT_TYPE_FOCUS: {
814 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
815 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800816 case AINPUT_EVENT_TYPE_CAPTURE: {
817 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
818 }
arthurhungb89ccb02020-12-30 16:19:01 +0800819 case AINPUT_EVENT_TYPE_DRAG: {
820 FAIL() << "Use 'consumeDragEvent' for DRAG events";
821 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800822 default: {
823 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
824 }
825 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800826 }
827
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100828 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
829 InputEvent* event = consume();
830 ASSERT_NE(nullptr, event) << mName.c_str()
831 << ": consumer should have returned non-NULL event.";
832 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
833 << "Got " << inputEventTypeToString(event->getType())
834 << " event instead of FOCUS event";
835
836 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
837 << mName.c_str() << ": event displayId should always be NONE.";
838
839 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
840 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
841 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
842 }
843
Prabir Pradhan99987712020-11-10 18:43:05 -0800844 void consumeCaptureEvent(bool hasCapture) {
845 const InputEvent* event = consume();
846 ASSERT_NE(nullptr, event) << mName.c_str()
847 << ": consumer should have returned non-NULL event.";
848 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
849 << "Got " << inputEventTypeToString(event->getType())
850 << " event instead of CAPTURE event";
851
852 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
853 << mName.c_str() << ": event displayId should always be NONE.";
854
855 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
856 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
857 }
858
arthurhungb89ccb02020-12-30 16:19:01 +0800859 void consumeDragEvent(bool isExiting, float x, float y) {
860 const InputEvent* event = consume();
861 ASSERT_NE(nullptr, event) << mName.c_str()
862 << ": consumer should have returned non-NULL event.";
863 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
864 << "Got " << inputEventTypeToString(event->getType())
865 << " event instead of DRAG event";
866
867 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
868 << mName.c_str() << ": event displayId should always be NONE.";
869
870 const auto& dragEvent = static_cast<const DragEvent&>(*event);
871 EXPECT_EQ(isExiting, dragEvent.isExiting());
872 EXPECT_EQ(x, dragEvent.getX());
873 EXPECT_EQ(y, dragEvent.getY());
874 }
875
chaviwd1c23182019-12-20 18:44:56 -0800876 void assertNoEvents() {
877 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700878 if (event == nullptr) {
879 return;
880 }
881 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
882 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
883 ADD_FAILURE() << "Received key event "
884 << KeyEvent::actionToString(keyEvent.getAction());
885 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
886 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
887 ADD_FAILURE() << "Received motion event "
888 << MotionEvent::actionToString(motionEvent.getAction());
889 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
890 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
891 ADD_FAILURE() << "Received focus event, hasFocus = "
892 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800893 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
894 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
895 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
896 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700897 }
898 FAIL() << mName.c_str()
899 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800900 }
901
902 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
903
904protected:
905 std::unique_ptr<InputConsumer> mConsumer;
906 PreallocatedInputEventFactory mEventFactory;
907
908 std::string mName;
909};
910
chaviw3277faf2021-05-19 16:45:23 -0500911class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -0800912public:
913 static const int32_t WIDTH = 600;
914 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800915
Chris Yea209fde2020-07-22 13:54:51 -0700916 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800917 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500918 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800919 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500920 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700921 base::Result<std::unique_ptr<InputChannel>> channel =
922 dispatcher->createInputChannel(name);
923 token = (*channel)->getConnectionToken();
924 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800925 }
926
927 inputApplicationHandle->updateInfo();
928 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
929
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500930 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700931 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800932 mInfo.name = name;
chaviw3277faf2021-05-19 16:45:23 -0500933 mInfo.type = WindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500934 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000935 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -0800936 mInfo.frameLeft = 0;
937 mInfo.frameTop = 0;
938 mInfo.frameRight = WIDTH;
939 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700940 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800941 mInfo.globalScaleFactor = 1.0;
942 mInfo.touchableRegion.clear();
943 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
944 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700945 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800946 mInfo.hasWallpaper = false;
947 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800948 mInfo.ownerPid = INJECTOR_PID;
949 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800950 mInfo.displayId = displayId;
951 }
952
Arthur Hungabbb9d82021-09-01 14:52:30 +0000953 sp<FakeWindowHandle> clone(
954 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
955 const sp<InputDispatcher>& dispatcher, int32_t displayId) {
956 sp<FakeWindowHandle> handle =
957 new FakeWindowHandle(inputApplicationHandle, dispatcher, mInfo.name + "(Mirror)",
958 displayId, mInfo.token);
959 return handle;
960 }
961
Vishnu Nair47074b82020-08-14 11:54:47 -0700962 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800963
Vishnu Nair958da932020-08-21 17:12:37 -0700964 void setVisible(bool visible) { mInfo.visible = visible; }
965
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700966 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500967 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700968 }
969
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700970 void setPaused(bool paused) { mInfo.paused = paused; }
971
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000972 void setAlpha(float alpha) { mInfo.alpha = alpha; }
973
chaviw3277faf2021-05-19 16:45:23 -0500974 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000975
Bernardo Rufino7393d172021-02-26 13:56:11 +0000976 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
977
chaviwd1c23182019-12-20 18:44:56 -0800978 void setFrame(const Rect& frame) {
979 mInfo.frameLeft = frame.left;
980 mInfo.frameTop = frame.top;
981 mInfo.frameRight = frame.right;
982 mInfo.frameBottom = frame.bottom;
arthurhungb89ccb02020-12-30 16:19:01 +0800983 mInfo.transform.set(-frame.left, -frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800984 mInfo.touchableRegion.clear();
985 mInfo.addTouchableRegion(frame);
986 }
987
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000988 void setType(WindowInfo::Type type) { mInfo.type = type; }
989
990 void setHasWallpaper(bool hasWallpaper) { mInfo.hasWallpaper = hasWallpaper; }
991
chaviw3277faf2021-05-19 16:45:23 -0500992 void addFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags |= flags; }
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +0000993
chaviw3277faf2021-05-19 16:45:23 -0500994 void setFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800995
chaviw3277faf2021-05-19 16:45:23 -0500996 void setInputFeatures(WindowInfo::Feature features) { mInfo.inputFeatures = features; }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500997
chaviw9eaa22c2020-07-01 16:21:27 -0700998 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
999 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1000 }
1001
1002 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001003
yunho.shinf4a80b82020-11-16 21:13:57 +09001004 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1005
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001006 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1007 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1008 expectedFlags);
1009 }
1010
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001011 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1012 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1013 }
1014
Svet Ganov5d3bc372020-01-26 23:11:07 -08001015 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001016 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001017 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
1018 expectedFlags);
1019 }
1020
1021 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001022 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001023 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
1024 expectedFlags);
1025 }
1026
1027 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001028 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001029 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1030 }
1031
1032 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1033 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001034 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1035 expectedFlags);
1036 }
1037
Svet Ganov5d3bc372020-01-26 23:11:07 -08001038 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001039 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1040 int32_t expectedFlags = 0) {
1041 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1042 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001043 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1044 }
1045
1046 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001047 int32_t expectedFlags = 0) {
1048 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1049 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001050 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1051 }
1052
1053 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001054 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001055 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1056 expectedFlags);
1057 }
1058
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001059 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1060 int32_t expectedFlags = 0) {
1061 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1062 expectedFlags);
1063 }
1064
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001065 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1066 ASSERT_NE(mInputReceiver, nullptr)
1067 << "Cannot consume events from a window with no receiver";
1068 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1069 }
1070
Prabir Pradhan99987712020-11-10 18:43:05 -08001071 void consumeCaptureEvent(bool hasCapture) {
1072 ASSERT_NE(mInputReceiver, nullptr)
1073 << "Cannot consume events from a window with no receiver";
1074 mInputReceiver->consumeCaptureEvent(hasCapture);
1075 }
1076
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001077 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1078 std::optional<int32_t> expectedDisplayId,
1079 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001080 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1081 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1082 expectedFlags);
1083 }
1084
arthurhungb89ccb02020-12-30 16:19:01 +08001085 void consumeDragEvent(bool isExiting, float x, float y) {
1086 mInputReceiver->consumeDragEvent(isExiting, x, y);
1087 }
1088
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001089 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001090 if (mInputReceiver == nullptr) {
1091 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1092 return std::nullopt;
1093 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001095 }
1096
1097 void finishEvent(uint32_t sequenceNum) {
1098 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1099 mInputReceiver->finishEvent(sequenceNum);
1100 }
1101
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001102 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1103 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1104 mInputReceiver->sendTimeline(inputEventId, timeline);
1105 }
1106
chaviwaf87b3e2019-10-01 16:59:28 -07001107 InputEvent* consume() {
1108 if (mInputReceiver == nullptr) {
1109 return nullptr;
1110 }
1111 return mInputReceiver->consume();
1112 }
1113
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001114 MotionEvent* consumeMotion() {
1115 InputEvent* event = consume();
1116 if (event == nullptr) {
1117 ADD_FAILURE() << "Consume failed : no event";
1118 return nullptr;
1119 }
1120 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1121 ADD_FAILURE() << "Instead of motion event, got "
1122 << inputEventTypeToString(event->getType());
1123 return nullptr;
1124 }
1125 return static_cast<MotionEvent*>(event);
1126 }
1127
Arthur Hungb92218b2018-08-14 12:00:21 +08001128 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001129 if (mInputReceiver == nullptr &&
chaviw3277faf2021-05-19 16:45:23 -05001130 mInfo.inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001131 return; // Can't receive events if the window does not have input channel
1132 }
1133 ASSERT_NE(nullptr, mInputReceiver)
1134 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001135 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001136 }
1137
chaviwaf87b3e2019-10-01 16:59:28 -07001138 sp<IBinder> getToken() { return mInfo.token; }
1139
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001140 const std::string& getName() { return mName; }
1141
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001142 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1143 mInfo.ownerPid = ownerPid;
1144 mInfo.ownerUid = ownerUid;
1145 }
1146
chaviwd1c23182019-12-20 18:44:56 -08001147private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001148 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001149 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001150 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001151};
1152
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001153std::atomic<int32_t> FakeWindowHandle::sId{1};
1154
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001155static InputEventInjectionResult injectKey(
1156 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
1157 int32_t displayId = ADISPLAY_ID_NONE,
1158 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001159 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1160 bool allowKeyRepeat = true) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001161 KeyEvent event;
1162 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1163
1164 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001165 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001166 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1167 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001168
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001169 int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
1170 if (!allowKeyRepeat) {
1171 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1172 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001173 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001174 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001175 injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001176}
1177
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001178static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
1179 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001180 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1181}
1182
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001183// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1184// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1185// has to be woken up to process the repeating key.
1186static InputEventInjectionResult injectKeyDownNoRepeat(const sp<InputDispatcher>& dispatcher,
1187 int32_t displayId = ADISPLAY_ID_NONE) {
1188 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1189 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1190 /* allowKeyRepeat */ false);
1191}
1192
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001193static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
1194 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001195 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1196}
1197
Garfield Tandf26e862020-07-01 20:18:19 -07001198class PointerBuilder {
1199public:
1200 PointerBuilder(int32_t id, int32_t toolType) {
1201 mProperties.clear();
1202 mProperties.id = id;
1203 mProperties.toolType = toolType;
1204 mCoords.clear();
1205 }
1206
1207 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1208
1209 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1210
1211 PointerBuilder& axis(int32_t axis, float value) {
1212 mCoords.setAxisValue(axis, value);
1213 return *this;
1214 }
1215
1216 PointerProperties buildProperties() const { return mProperties; }
1217
1218 PointerCoords buildCoords() const { return mCoords; }
1219
1220private:
1221 PointerProperties mProperties;
1222 PointerCoords mCoords;
1223};
1224
1225class MotionEventBuilder {
1226public:
1227 MotionEventBuilder(int32_t action, int32_t source) {
1228 mAction = action;
1229 mSource = source;
1230 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1231 }
1232
1233 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1234 mEventTime = eventTime;
1235 return *this;
1236 }
1237
1238 MotionEventBuilder& displayId(int32_t displayId) {
1239 mDisplayId = displayId;
1240 return *this;
1241 }
1242
1243 MotionEventBuilder& actionButton(int32_t actionButton) {
1244 mActionButton = actionButton;
1245 return *this;
1246 }
1247
arthurhung6d4bed92021-03-17 11:59:33 +08001248 MotionEventBuilder& buttonState(int32_t buttonState) {
1249 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001250 return *this;
1251 }
1252
1253 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1254 mRawXCursorPosition = rawXCursorPosition;
1255 return *this;
1256 }
1257
1258 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1259 mRawYCursorPosition = rawYCursorPosition;
1260 return *this;
1261 }
1262
1263 MotionEventBuilder& pointer(PointerBuilder pointer) {
1264 mPointers.push_back(pointer);
1265 return *this;
1266 }
1267
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001268 MotionEventBuilder& addFlag(uint32_t flags) {
1269 mFlags |= flags;
1270 return *this;
1271 }
1272
Garfield Tandf26e862020-07-01 20:18:19 -07001273 MotionEvent build() {
1274 std::vector<PointerProperties> pointerProperties;
1275 std::vector<PointerCoords> pointerCoords;
1276 for (const PointerBuilder& pointer : mPointers) {
1277 pointerProperties.push_back(pointer.buildProperties());
1278 pointerCoords.push_back(pointer.buildCoords());
1279 }
1280
1281 // Set mouse cursor position for the most common cases to avoid boilerplate.
1282 if (mSource == AINPUT_SOURCE_MOUSE &&
1283 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1284 mPointers.size() == 1) {
1285 mRawXCursorPosition = pointerCoords[0].getX();
1286 mRawYCursorPosition = pointerCoords[0].getY();
1287 }
1288
1289 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001290 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001291 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001292 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001293 mButtonState, MotionClassification::NONE, identityTransform,
1294 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001295 mRawYCursorPosition, identityTransform, mEventTime, mEventTime,
1296 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001297
1298 return event;
1299 }
1300
1301private:
1302 int32_t mAction;
1303 int32_t mSource;
1304 nsecs_t mEventTime;
1305 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1306 int32_t mActionButton{0};
1307 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001308 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001309 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1310 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1311
1312 std::vector<PointerBuilder> mPointers;
1313};
1314
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001315static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001316 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1317 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001318 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001319 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1320 injectionTimeout,
1321 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1322}
1323
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001324static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001325 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1326 const PointF& position,
1327 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001328 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1329 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001330 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001331 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001332 MotionEvent event = MotionEventBuilder(action, source)
1333 .displayId(displayId)
1334 .eventTime(eventTime)
1335 .rawXCursorPosition(cursorPosition.x)
1336 .rawYCursorPosition(cursorPosition.y)
1337 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1338 .x(position.x)
1339 .y(position.y))
1340 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001341
1342 // Inject event until dispatch out.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001343 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode);
Arthur Hungb92218b2018-08-14 12:00:21 +08001344}
1345
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001346static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1347 int32_t source, int32_t displayId,
1348 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001349 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001350}
1351
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001352static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1353 int32_t source, int32_t displayId,
1354 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001356}
1357
Jackal Guof9696682018-10-05 12:23:23 +08001358static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1359 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1360 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001361 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1362 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1363 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001364
1365 return args;
1366}
1367
chaviwd1c23182019-12-20 18:44:56 -08001368static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1369 const std::vector<PointF>& points) {
1370 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001371 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1372 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1373 }
1374
chaviwd1c23182019-12-20 18:44:56 -08001375 PointerProperties pointerProperties[pointerCount];
1376 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001377
chaviwd1c23182019-12-20 18:44:56 -08001378 for (size_t i = 0; i < pointerCount; i++) {
1379 pointerProperties[i].clear();
1380 pointerProperties[i].id = i;
1381 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001382
chaviwd1c23182019-12-20 18:44:56 -08001383 pointerCoords[i].clear();
1384 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1385 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1386 }
Jackal Guof9696682018-10-05 12:23:23 +08001387
1388 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1389 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001390 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001391 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1392 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001393 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1394 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001395 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1396 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001397
1398 return args;
1399}
1400
chaviwd1c23182019-12-20 18:44:56 -08001401static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1402 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1403}
1404
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001405static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1406 const PointerCaptureRequest& request) {
1407 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001408}
1409
Arthur Hungb92218b2018-08-14 12:00:21 +08001410TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001412 sp<FakeWindowHandle> window =
1413 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001414
Arthur Hung72d8dc32020-03-28 00:48:39 +00001415 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1417 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001419
1420 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001421 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001422}
1423
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001424/**
1425 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1426 * To ensure that window receives only events that were directly inside of it, add
1427 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1428 * when finding touched windows.
1429 * This test serves as a sanity check for the next test, where setInputWindows is
1430 * called twice.
1431 */
1432TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001433 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001434 sp<FakeWindowHandle> window =
1435 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1436 window->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05001437 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001438
1439 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001441 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1442 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001443 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001444
1445 // Window should receive motion event.
1446 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1447}
1448
1449/**
1450 * Calling setInputWindows twice, with the same info, should not cause any issues.
1451 * To ensure that window receives only events that were directly inside of it, add
1452 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1453 * when finding touched windows.
1454 */
1455TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001456 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001457 sp<FakeWindowHandle> window =
1458 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1459 window->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05001460 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001461
1462 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001465 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1466 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001468
1469 // Window should receive motion event.
1470 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1471}
1472
Arthur Hungb92218b2018-08-14 12:00:21 +08001473// The foreground window should receive the first touch down event.
1474TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001475 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001476 sp<FakeWindowHandle> windowTop =
1477 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1478 sp<FakeWindowHandle> windowSecond =
1479 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001480
Arthur Hung72d8dc32020-03-28 00:48:39 +00001481 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1483 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1484 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001485
1486 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001487 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001488 windowSecond->assertNoEvents();
1489}
1490
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001491/**
1492 * Two windows: A top window, and a wallpaper behind the window.
1493 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1494 * gets ACTION_CANCEL.
1495 * 1. foregroundWindow <-- has wallpaper (hasWallpaper=true)
1496 * 2. wallpaperWindow <-- is wallpaper (type=InputWindowInfo::Type::WALLPAPER)
1497 */
1498TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1500 sp<FakeWindowHandle> foregroundWindow =
1501 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1502 foregroundWindow->setHasWallpaper(true);
1503 sp<FakeWindowHandle> wallpaperWindow =
1504 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1505 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1506 constexpr int expectedWallpaperFlags =
1507 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1508
1509 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1511 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1512 {100, 200}))
1513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1514
1515 // Both foreground window and its wallpaper should receive the touch down
1516 foregroundWindow->consumeMotionDown();
1517 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1518
1519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1520 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1521 ADISPLAY_ID_DEFAULT, {110, 200}))
1522 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1523
1524 foregroundWindow->consumeMotionMove();
1525 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1526
1527 // Now the foreground window goes away, but the wallpaper stays
1528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1529 foregroundWindow->consumeMotionCancel();
1530 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1531 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1532}
1533
1534/**
1535 * A single window that receives touch (on top), and a wallpaper window underneath it.
1536 * The top window gets a multitouch gesture.
1537 * Ensure that wallpaper gets the same gesture.
1538 */
1539TEST_F(InputDispatcherTest, WallpaperWindow_ReceivesMultiTouch) {
1540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1541 sp<FakeWindowHandle> window =
1542 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1543 window->setHasWallpaper(true);
1544
1545 sp<FakeWindowHandle> wallpaperWindow =
1546 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1547 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1548 constexpr int expectedWallpaperFlags =
1549 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1550
1551 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1552
1553 // Touch down on top window
1554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1555 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1556 {100, 100}))
1557 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1558
1559 // Both top window and its wallpaper should receive the touch down
1560 window->consumeMotionDown();
1561 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1562
1563 // Second finger down on the top window
1564 const MotionEvent secondFingerDownEvent =
1565 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1566 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1567 AINPUT_SOURCE_TOUCHSCREEN)
1568 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1569 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1570 .x(100)
1571 .y(100))
1572 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1573 .x(150)
1574 .y(150))
1575 .build();
1576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1577 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1578 InputEventInjectionSync::WAIT_FOR_RESULT))
1579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1580
1581 window->consumeMotionPointerDown(1 /* pointerIndex */);
1582 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1583 expectedWallpaperFlags);
1584 window->assertNoEvents();
1585 wallpaperWindow->assertNoEvents();
1586}
1587
1588/**
1589 * Two windows: a window on the left and window on the right.
1590 * A third window, wallpaper, is behind both windows, and spans both top windows.
1591 * The first touch down goes to the left window. A second pointer touches down on the right window.
1592 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1593 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1594 * ACTION_POINTER_DOWN(1).
1595 */
1596TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1598 sp<FakeWindowHandle> leftWindow =
1599 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1600 leftWindow->setFrame(Rect(0, 0, 200, 200));
1601 leftWindow->setFlags(WindowInfo::Flag::SPLIT_TOUCH | WindowInfo::Flag::NOT_TOUCH_MODAL);
1602 leftWindow->setHasWallpaper(true);
1603
1604 sp<FakeWindowHandle> rightWindow =
1605 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1606 rightWindow->setFrame(Rect(200, 0, 400, 200));
1607 rightWindow->setFlags(WindowInfo::Flag::SPLIT_TOUCH | WindowInfo::Flag::NOT_TOUCH_MODAL);
1608 rightWindow->setHasWallpaper(true);
1609
1610 sp<FakeWindowHandle> wallpaperWindow =
1611 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1612 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
1613 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1614 constexpr int expectedWallpaperFlags =
1615 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1616
1617 mDispatcher->setInputWindows(
1618 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1619
1620 // Touch down on left window
1621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1622 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1623 {100, 100}))
1624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1625
1626 // Both foreground window and its wallpaper should receive the touch down
1627 leftWindow->consumeMotionDown();
1628 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1629
1630 // Second finger down on the right window
1631 const MotionEvent secondFingerDownEvent =
1632 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1633 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1634 AINPUT_SOURCE_TOUCHSCREEN)
1635 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1636 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1637 .x(100)
1638 .y(100))
1639 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1640 .x(300)
1641 .y(100))
1642 .build();
1643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1644 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1645 InputEventInjectionSync::WAIT_FOR_RESULT))
1646 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1647
1648 leftWindow->consumeMotionMove();
1649 // Since the touch is split, right window gets ACTION_DOWN
1650 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1651 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1652 expectedWallpaperFlags);
1653
1654 // Now, leftWindow, which received the first finger, disappears.
1655 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1656 leftWindow->consumeMotionCancel();
1657 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1658 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1659
1660 // The pointer that's still down on the right window moves, and goes to the right window only.
1661 // As far as the dispatcher's concerned though, both pointers are still present.
1662 const MotionEvent secondFingerMoveEvent =
1663 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1664 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1665 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1666 .x(100)
1667 .y(100))
1668 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1669 .x(310)
1670 .y(110))
1671 .build();
1672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1673 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1674 InputEventInjectionSync::WAIT_FOR_RESULT));
1675 rightWindow->consumeMotionMove();
1676
1677 leftWindow->assertNoEvents();
1678 rightWindow->assertNoEvents();
1679 wallpaperWindow->assertNoEvents();
1680}
1681
Garfield Tandf26e862020-07-01 20:18:19 -07001682TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001684 sp<FakeWindowHandle> windowLeft =
1685 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1686 windowLeft->setFrame(Rect(0, 0, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001687 windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001688 sp<FakeWindowHandle> windowRight =
1689 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1690 windowRight->setFrame(Rect(600, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001691 windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001692
1693 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1694
1695 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1696
1697 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001699 injectMotionEvent(mDispatcher,
1700 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1701 AINPUT_SOURCE_MOUSE)
1702 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1703 .x(900)
1704 .y(400))
1705 .build()));
1706 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1707 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1708 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1709 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1710
1711 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001713 injectMotionEvent(mDispatcher,
1714 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1715 AINPUT_SOURCE_MOUSE)
1716 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1717 .x(300)
1718 .y(400))
1719 .build()));
1720 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1721 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1722 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1723 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1724 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1725 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1726
1727 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001729 injectMotionEvent(mDispatcher,
1730 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1731 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1732 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1733 .x(300)
1734 .y(400))
1735 .build()));
1736 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1737
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001739 injectMotionEvent(mDispatcher,
1740 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1741 AINPUT_SOURCE_MOUSE)
1742 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1743 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1744 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1745 .x(300)
1746 .y(400))
1747 .build()));
1748 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1749 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1750
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001752 injectMotionEvent(mDispatcher,
1753 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1754 AINPUT_SOURCE_MOUSE)
1755 .buttonState(0)
1756 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1757 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1758 .x(300)
1759 .y(400))
1760 .build()));
1761 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1762 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1763
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001765 injectMotionEvent(mDispatcher,
1766 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1767 .buttonState(0)
1768 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1769 .x(300)
1770 .y(400))
1771 .build()));
1772 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1773
1774 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001776 injectMotionEvent(mDispatcher,
1777 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1778 AINPUT_SOURCE_MOUSE)
1779 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1780 .x(900)
1781 .y(400))
1782 .build()));
1783 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1784 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1785 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1786 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1787 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1788 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1789}
1790
1791// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1792// directly in this test.
1793TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001795 sp<FakeWindowHandle> window =
1796 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1797 window->setFrame(Rect(0, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001798 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001799
1800 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1801
1802 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1803
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001805 injectMotionEvent(mDispatcher,
1806 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1807 AINPUT_SOURCE_MOUSE)
1808 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1809 .x(300)
1810 .y(400))
1811 .build()));
1812 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1813 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1814
1815 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001817 injectMotionEvent(mDispatcher,
1818 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1819 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1820 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1821 .x(300)
1822 .y(400))
1823 .build()));
1824 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1825
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001827 injectMotionEvent(mDispatcher,
1828 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1829 AINPUT_SOURCE_MOUSE)
1830 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1831 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1832 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1833 .x(300)
1834 .y(400))
1835 .build()));
1836 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1837 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1838
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001840 injectMotionEvent(mDispatcher,
1841 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1842 AINPUT_SOURCE_MOUSE)
1843 .buttonState(0)
1844 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1845 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1846 .x(300)
1847 .y(400))
1848 .build()));
1849 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1850 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1851
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001853 injectMotionEvent(mDispatcher,
1854 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1855 .buttonState(0)
1856 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1857 .x(300)
1858 .y(400))
1859 .build()));
1860 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1861
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001863 injectMotionEvent(mDispatcher,
1864 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1865 AINPUT_SOURCE_MOUSE)
1866 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1867 .x(300)
1868 .y(400))
1869 .build()));
1870 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1871 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1872}
1873
Garfield Tan00f511d2019-06-12 16:55:40 -07001874TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001876
1877 sp<FakeWindowHandle> windowLeft =
1878 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1879 windowLeft->setFrame(Rect(0, 0, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001880 windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001881 sp<FakeWindowHandle> windowRight =
1882 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1883 windowRight->setFrame(Rect(600, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001884 windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001885
1886 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1887
Arthur Hung72d8dc32020-03-28 00:48:39 +00001888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001889
1890 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1891 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001893 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001894 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001895 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001896 windowRight->assertNoEvents();
1897}
1898
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001899TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001901 sp<FakeWindowHandle> window =
1902 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001903 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001904
Arthur Hung72d8dc32020-03-28 00:48:39 +00001905 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001906 setFocusedWindow(window);
1907
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001908 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001909
1910 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1911 mDispatcher->notifyKey(&keyArgs);
1912
1913 // Window should receive key down event.
1914 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1915
1916 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1917 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001918 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001919 mDispatcher->notifyDeviceReset(&args);
1920 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1921 AKEY_EVENT_FLAG_CANCELED);
1922}
1923
1924TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001925 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001926 sp<FakeWindowHandle> window =
1927 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1928
Arthur Hung72d8dc32020-03-28 00:48:39 +00001929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001930
1931 NotifyMotionArgs motionArgs =
1932 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1933 ADISPLAY_ID_DEFAULT);
1934 mDispatcher->notifyMotion(&motionArgs);
1935
1936 // Window should receive motion down event.
1937 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1938
1939 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1940 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001941 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001942 mDispatcher->notifyDeviceReset(&args);
1943 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1944 0 /*expectedFlags*/);
1945}
1946
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001947using TransferFunction =
1948 std::function<bool(sp<InputDispatcher> dispatcher, sp<IBinder>, sp<IBinder>)>;
1949
1950class TransferTouchFixture : public InputDispatcherTest,
1951 public ::testing::WithParamInterface<TransferFunction> {};
1952
1953TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001955
1956 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001957 sp<FakeWindowHandle> firstWindow =
1958 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1959 sp<FakeWindowHandle> secondWindow =
1960 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001961
1962 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001963 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001964
1965 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001966 NotifyMotionArgs downMotionArgs =
1967 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1968 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001969 mDispatcher->notifyMotion(&downMotionArgs);
1970 // Only the first window should get the down event
1971 firstWindow->consumeMotionDown();
1972 secondWindow->assertNoEvents();
1973
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001974 // Transfer touch to the second window
1975 TransferFunction f = GetParam();
1976 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
1977 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001978 // The first window gets cancel and the second gets down
1979 firstWindow->consumeMotionCancel();
1980 secondWindow->consumeMotionDown();
1981
1982 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001983 NotifyMotionArgs upMotionArgs =
1984 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1985 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001986 mDispatcher->notifyMotion(&upMotionArgs);
1987 // The first window gets no events and the second gets up
1988 firstWindow->assertNoEvents();
1989 secondWindow->consumeMotionUp();
1990}
1991
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001992TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001993 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001994
1995 PointF touchPoint = {10, 10};
1996
1997 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001998 sp<FakeWindowHandle> firstWindow =
1999 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2000 sp<FakeWindowHandle> secondWindow =
2001 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002002
2003 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002004 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002005
2006 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002007 NotifyMotionArgs downMotionArgs =
2008 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2009 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002010 mDispatcher->notifyMotion(&downMotionArgs);
2011 // Only the first window should get the down event
2012 firstWindow->consumeMotionDown();
2013 secondWindow->assertNoEvents();
2014
2015 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002016 NotifyMotionArgs pointerDownMotionArgs =
2017 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2018 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2019 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2020 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002021 mDispatcher->notifyMotion(&pointerDownMotionArgs);
2022 // Only the first window should get the pointer down event
2023 firstWindow->consumeMotionPointerDown(1);
2024 secondWindow->assertNoEvents();
2025
2026 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002027 TransferFunction f = GetParam();
2028 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2029 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002030 // The first window gets cancel and the second gets down and pointer down
2031 firstWindow->consumeMotionCancel();
2032 secondWindow->consumeMotionDown();
2033 secondWindow->consumeMotionPointerDown(1);
2034
2035 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002036 NotifyMotionArgs pointerUpMotionArgs =
2037 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2038 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2039 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2040 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002041 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2042 // The first window gets nothing and the second gets pointer up
2043 firstWindow->assertNoEvents();
2044 secondWindow->consumeMotionPointerUp(1);
2045
2046 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002047 NotifyMotionArgs upMotionArgs =
2048 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2049 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002050 mDispatcher->notifyMotion(&upMotionArgs);
2051 // The first window gets nothing and the second gets up
2052 firstWindow->assertNoEvents();
2053 secondWindow->consumeMotionUp();
2054}
2055
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002056// For the cases of single pointer touch and two pointers non-split touch, the api's
2057// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
2058// for the case where there are multiple pointers split across several windows.
2059INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
2060 ::testing::Values(
2061 [&](sp<InputDispatcher> dispatcher, sp<IBinder> /*ignored*/,
2062 sp<IBinder> destChannelToken) {
2063 return dispatcher->transferTouch(destChannelToken);
2064 },
2065 [&](sp<InputDispatcher> dispatcher, sp<IBinder> from,
2066 sp<IBinder> to) {
2067 return dispatcher->transferTouchFocus(from, to,
2068 false /*isDragAndDrop*/);
2069 }));
2070
Svet Ganov5d3bc372020-01-26 23:11:07 -08002071TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002072 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002073
2074 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002075 sp<FakeWindowHandle> firstWindow =
2076 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002077 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002078 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002079
2080 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002081 sp<FakeWindowHandle> secondWindow =
2082 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002083 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002084 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002085
2086 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002087 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002088
2089 PointF pointInFirst = {300, 200};
2090 PointF pointInSecond = {300, 600};
2091
2092 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002093 NotifyMotionArgs firstDownMotionArgs =
2094 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2095 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002096 mDispatcher->notifyMotion(&firstDownMotionArgs);
2097 // Only the first window should get the down event
2098 firstWindow->consumeMotionDown();
2099 secondWindow->assertNoEvents();
2100
2101 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002102 NotifyMotionArgs secondDownMotionArgs =
2103 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2104 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2105 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2106 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002107 mDispatcher->notifyMotion(&secondDownMotionArgs);
2108 // The first window gets a move and the second a down
2109 firstWindow->consumeMotionMove();
2110 secondWindow->consumeMotionDown();
2111
2112 // Transfer touch focus to the second window
2113 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
2114 // The first window gets cancel and the new gets pointer down (it already saw down)
2115 firstWindow->consumeMotionCancel();
2116 secondWindow->consumeMotionPointerDown(1);
2117
2118 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002119 NotifyMotionArgs pointerUpMotionArgs =
2120 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2121 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2122 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2123 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002124 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2125 // The first window gets nothing and the second gets pointer up
2126 firstWindow->assertNoEvents();
2127 secondWindow->consumeMotionPointerUp(1);
2128
2129 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002130 NotifyMotionArgs upMotionArgs =
2131 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2132 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002133 mDispatcher->notifyMotion(&upMotionArgs);
2134 // The first window gets nothing and the second gets up
2135 firstWindow->assertNoEvents();
2136 secondWindow->consumeMotionUp();
2137}
2138
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002139// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
2140// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
2141// touch is not supported, so the touch should continue on those windows and the transferred-to
2142// window should get nothing.
2143TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
2144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2145
2146 // Create a non touch modal window that supports split touch
2147 sp<FakeWindowHandle> firstWindow =
2148 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2149 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002150 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002151
2152 // Create a non touch modal window that supports split touch
2153 sp<FakeWindowHandle> secondWindow =
2154 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2155 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002156 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002157
2158 // Add the windows to the dispatcher
2159 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2160
2161 PointF pointInFirst = {300, 200};
2162 PointF pointInSecond = {300, 600};
2163
2164 // Send down to the first window
2165 NotifyMotionArgs firstDownMotionArgs =
2166 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2167 ADISPLAY_ID_DEFAULT, {pointInFirst});
2168 mDispatcher->notifyMotion(&firstDownMotionArgs);
2169 // Only the first window should get the down event
2170 firstWindow->consumeMotionDown();
2171 secondWindow->assertNoEvents();
2172
2173 // Send down to the second window
2174 NotifyMotionArgs secondDownMotionArgs =
2175 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2176 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2177 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2178 {pointInFirst, pointInSecond});
2179 mDispatcher->notifyMotion(&secondDownMotionArgs);
2180 // The first window gets a move and the second a down
2181 firstWindow->consumeMotionMove();
2182 secondWindow->consumeMotionDown();
2183
2184 // Transfer touch focus to the second window
2185 const bool transferred = mDispatcher->transferTouch(secondWindow->getToken());
2186 // The 'transferTouch' call should not succeed, because there are 2 touched windows
2187 ASSERT_FALSE(transferred);
2188 firstWindow->assertNoEvents();
2189 secondWindow->assertNoEvents();
2190
2191 // The rest of the dispatch should proceed as normal
2192 // Send pointer up to the second window
2193 NotifyMotionArgs pointerUpMotionArgs =
2194 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2195 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2196 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2197 {pointInFirst, pointInSecond});
2198 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2199 // The first window gets MOVE and the second gets pointer up
2200 firstWindow->consumeMotionMove();
2201 secondWindow->consumeMotionUp();
2202
2203 // Send up event to the first window
2204 NotifyMotionArgs upMotionArgs =
2205 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2206 ADISPLAY_ID_DEFAULT);
2207 mDispatcher->notifyMotion(&upMotionArgs);
2208 // The first window gets nothing and the second gets up
2209 firstWindow->consumeMotionUp();
2210 secondWindow->assertNoEvents();
2211}
2212
Arthur Hungabbb9d82021-09-01 14:52:30 +00002213// This case will create two windows and one mirrored window on the default display and mirror
2214// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
2215// the windows info of second display before default display.
2216TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
2217 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2218 sp<FakeWindowHandle> firstWindowInPrimary =
2219 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2220 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
2221 firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2222 sp<FakeWindowHandle> secondWindowInPrimary =
2223 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2224 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2225 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2226
2227 sp<FakeWindowHandle> mirrorWindowInPrimary =
2228 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2229 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
2230 mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2231
2232 sp<FakeWindowHandle> firstWindowInSecondary =
2233 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2234 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
2235 firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2236
2237 sp<FakeWindowHandle> secondWindowInSecondary =
2238 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2239 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2240 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2241
2242 // Update window info, let it find window handle of second display first.
2243 mDispatcher->setInputWindows(
2244 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2245 {ADISPLAY_ID_DEFAULT,
2246 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2247
2248 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2249 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2250 {50, 50}))
2251 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2252
2253 // Window should receive motion event.
2254 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2255
2256 // Transfer touch focus
2257 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
2258 secondWindowInPrimary->getToken()));
2259 // The first window gets cancel.
2260 firstWindowInPrimary->consumeMotionCancel();
2261 secondWindowInPrimary->consumeMotionDown();
2262
2263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2264 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2265 ADISPLAY_ID_DEFAULT, {150, 50}))
2266 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2267 firstWindowInPrimary->assertNoEvents();
2268 secondWindowInPrimary->consumeMotionMove();
2269
2270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2271 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2272 {150, 50}))
2273 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2274 firstWindowInPrimary->assertNoEvents();
2275 secondWindowInPrimary->consumeMotionUp();
2276}
2277
2278// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
2279// 'transferTouch' api.
2280TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
2281 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2282 sp<FakeWindowHandle> firstWindowInPrimary =
2283 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2284 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
2285 firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2286 sp<FakeWindowHandle> secondWindowInPrimary =
2287 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2288 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2289 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2290
2291 sp<FakeWindowHandle> mirrorWindowInPrimary =
2292 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2293 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
2294 mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2295
2296 sp<FakeWindowHandle> firstWindowInSecondary =
2297 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2298 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
2299 firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2300
2301 sp<FakeWindowHandle> secondWindowInSecondary =
2302 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2303 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2304 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2305
2306 // Update window info, let it find window handle of second display first.
2307 mDispatcher->setInputWindows(
2308 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2309 {ADISPLAY_ID_DEFAULT,
2310 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2311
2312 // Touch on second display.
2313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2314 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
2315 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2316
2317 // Window should receive motion event.
2318 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2319
2320 // Transfer touch focus
2321 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken()));
2322
2323 // The first window gets cancel.
2324 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
2325 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2326
2327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2328 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2329 SECOND_DISPLAY_ID, {150, 50}))
2330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2331 firstWindowInPrimary->assertNoEvents();
2332 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
2333
2334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2335 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
2336 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2337 firstWindowInPrimary->assertNoEvents();
2338 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
2339}
2340
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002341TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002343 sp<FakeWindowHandle> window =
2344 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2345
Vishnu Nair47074b82020-08-14 11:54:47 -07002346 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002347 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002348 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002349
2350 window->consumeFocusEvent(true);
2351
2352 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2353 mDispatcher->notifyKey(&keyArgs);
2354
2355 // Window should receive key down event.
2356 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2357}
2358
2359TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002361 sp<FakeWindowHandle> window =
2362 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2363
Arthur Hung72d8dc32020-03-28 00:48:39 +00002364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002365
2366 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2367 mDispatcher->notifyKey(&keyArgs);
2368 mDispatcher->waitForIdle();
2369
2370 window->assertNoEvents();
2371}
2372
2373// If a window is touchable, but does not have focus, it should receive motion events, but not keys
2374TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07002375 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002376 sp<FakeWindowHandle> window =
2377 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2378
Arthur Hung72d8dc32020-03-28 00:48:39 +00002379 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002380
2381 // Send key
2382 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2383 mDispatcher->notifyKey(&keyArgs);
2384 // Send motion
2385 NotifyMotionArgs motionArgs =
2386 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2387 ADISPLAY_ID_DEFAULT);
2388 mDispatcher->notifyMotion(&motionArgs);
2389
2390 // Window should receive only the motion event
2391 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2392 window->assertNoEvents(); // Key event or focus event will not be received
2393}
2394
arthurhungea3f4fc2020-12-21 23:18:53 +08002395TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
2396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2397
2398 // Create first non touch modal window that supports split touch
2399 sp<FakeWindowHandle> firstWindow =
2400 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2401 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002402 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
arthurhungea3f4fc2020-12-21 23:18:53 +08002403
2404 // Create second non touch modal window that supports split touch
2405 sp<FakeWindowHandle> secondWindow =
2406 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2407 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002408 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
arthurhungea3f4fc2020-12-21 23:18:53 +08002409
2410 // Add the windows to the dispatcher
2411 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2412
2413 PointF pointInFirst = {300, 200};
2414 PointF pointInSecond = {300, 600};
2415
2416 // Send down to the first window
2417 NotifyMotionArgs firstDownMotionArgs =
2418 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2419 ADISPLAY_ID_DEFAULT, {pointInFirst});
2420 mDispatcher->notifyMotion(&firstDownMotionArgs);
2421 // Only the first window should get the down event
2422 firstWindow->consumeMotionDown();
2423 secondWindow->assertNoEvents();
2424
2425 // Send down to the second window
2426 NotifyMotionArgs secondDownMotionArgs =
2427 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2428 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2429 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2430 {pointInFirst, pointInSecond});
2431 mDispatcher->notifyMotion(&secondDownMotionArgs);
2432 // The first window gets a move and the second a down
2433 firstWindow->consumeMotionMove();
2434 secondWindow->consumeMotionDown();
2435
2436 // Send pointer cancel to the second window
2437 NotifyMotionArgs pointerUpMotionArgs =
2438 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2439 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2440 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2441 {pointInFirst, pointInSecond});
2442 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
2443 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2444 // The first window gets move and the second gets cancel.
2445 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2446 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2447
2448 // Send up event.
2449 NotifyMotionArgs upMotionArgs =
2450 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2451 ADISPLAY_ID_DEFAULT);
2452 mDispatcher->notifyMotion(&upMotionArgs);
2453 // The first window gets up and the second gets nothing.
2454 firstWindow->consumeMotionUp();
2455 secondWindow->assertNoEvents();
2456}
2457
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00002458TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
2459 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2460
2461 sp<FakeWindowHandle> window =
2462 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2464 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
2465 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
2466 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
2467
2468 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
2469 window->assertNoEvents();
2470 mDispatcher->waitForIdle();
2471}
2472
chaviwd1c23182019-12-20 18:44:56 -08002473class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00002474public:
2475 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08002476 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07002477 base::Result<std::unique_ptr<InputChannel>> channel =
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +00002478 dispatcher->createInputMonitor(displayId, isGestureMonitor, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07002479 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00002480 }
2481
chaviwd1c23182019-12-20 18:44:56 -08002482 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
2483
2484 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2485 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
2486 expectedDisplayId, expectedFlags);
2487 }
2488
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002489 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
2490
2491 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
2492
chaviwd1c23182019-12-20 18:44:56 -08002493 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2494 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
2495 expectedDisplayId, expectedFlags);
2496 }
2497
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002498 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2499 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
2500 expectedDisplayId, expectedFlags);
2501 }
2502
chaviwd1c23182019-12-20 18:44:56 -08002503 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2504 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
2505 expectedDisplayId, expectedFlags);
2506 }
2507
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002508 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2509 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2510 expectedDisplayId, expectedFlags);
2511 }
2512
Evan Rosky84f07f02021-04-16 10:42:42 -07002513 MotionEvent* consumeMotion() {
2514 InputEvent* event = mInputReceiver->consume();
2515 if (!event) {
2516 ADD_FAILURE() << "No event was produced";
2517 return nullptr;
2518 }
2519 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
2520 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
2521 return nullptr;
2522 }
2523 return static_cast<MotionEvent*>(event);
2524 }
2525
chaviwd1c23182019-12-20 18:44:56 -08002526 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
2527
2528private:
2529 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00002530};
2531
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002532/**
2533 * Two entities that receive touch: A window, and a global monitor.
2534 * The touch goes to the window, and then the window disappears.
2535 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
2536 * for the monitor, as well.
2537 * 1. foregroundWindow
2538 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
2539 */
2540TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_GlobalMonitorTouchIsCanceled) {
2541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2542 sp<FakeWindowHandle> window =
2543 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2544
2545 FakeMonitorReceiver monitor =
2546 FakeMonitorReceiver(mDispatcher, "GlobalMonitor", ADISPLAY_ID_DEFAULT,
2547 false /*isGestureMonitor*/);
2548
2549 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2551 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2552 {100, 200}))
2553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2554
2555 // Both the foreground window and the global monitor should receive the touch down
2556 window->consumeMotionDown();
2557 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2558
2559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2560 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2561 ADISPLAY_ID_DEFAULT, {110, 200}))
2562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2563
2564 window->consumeMotionMove();
2565 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
2566
2567 // Now the foreground window goes away
2568 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2569 window->consumeMotionCancel();
2570 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
2571
2572 // If more events come in, there will be no more foreground window to send them to. This will
2573 // cause a cancel for the monitor, as well.
2574 ASSERT_EQ(InputEventInjectionResult::FAILED,
2575 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2576 ADISPLAY_ID_DEFAULT, {120, 200}))
2577 << "Injection should fail because the window was removed";
2578 window->assertNoEvents();
2579 // Global monitor now gets the cancel
2580 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
2581}
2582
Michael Wright3a240c42019-12-10 20:53:41 +00002583// Tests for gesture monitors
2584TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002585 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002586 sp<FakeWindowHandle> window =
2587 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002588 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002589
chaviwd1c23182019-12-20 18:44:56 -08002590 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2591 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002592
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002594 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002596 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002597 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002598}
2599
2600TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002602 sp<FakeWindowHandle> window =
2603 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2604
2605 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002606 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00002607
Arthur Hung72d8dc32020-03-28 00:48:39 +00002608 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002609 setFocusedWindow(window);
2610
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002611 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00002612
chaviwd1c23182019-12-20 18:44:56 -08002613 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2614 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002615
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2617 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002618 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002619 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00002620}
2621
2622TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002624 sp<FakeWindowHandle> window =
2625 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002626 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002627
chaviwd1c23182019-12-20 18:44:56 -08002628 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2629 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002630
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002632 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002633 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002634 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002635 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002636
2637 window->releaseChannel();
2638
chaviwd1c23182019-12-20 18:44:56 -08002639 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00002640
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002642 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08002644 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002645}
2646
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002647TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
2648 FakeMonitorReceiver monitor =
2649 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2650 true /*isGestureMonitor*/);
2651
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002653 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
2654 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
2655 ASSERT_TRUE(consumeSeq);
2656
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002657 mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002658 monitor.finishEvent(*consumeSeq);
2659 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002660 mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002661}
2662
Evan Rosky84f07f02021-04-16 10:42:42 -07002663// Tests for gesture monitors
2664TEST_F(InputDispatcherTest, GestureMonitor_NoWindowTransform) {
2665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2666 sp<FakeWindowHandle> window =
2667 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2668 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2669 window->setWindowOffset(20, 40);
2670 window->setWindowTransform(0, 1, -1, 0);
2671
2672 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2673 true /*isGestureMonitor*/);
2674
2675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2676 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2678 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2679 MotionEvent* event = monitor.consumeMotion();
2680 // Even though window has transform, gesture monitor must not.
2681 ASSERT_EQ(ui::Transform(), event->getTransform());
2682}
2683
chaviw81e2bb92019-12-18 15:03:51 -08002684TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002685 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08002686 sp<FakeWindowHandle> window =
2687 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2688
Arthur Hung72d8dc32020-03-28 00:48:39 +00002689 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08002690
2691 NotifyMotionArgs motionArgs =
2692 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2693 ADISPLAY_ID_DEFAULT);
2694
2695 mDispatcher->notifyMotion(&motionArgs);
2696 // Window should receive motion down event.
2697 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2698
2699 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002700 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08002701 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2702 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
2703 motionArgs.pointerCoords[0].getX() - 10);
2704
2705 mDispatcher->notifyMotion(&motionArgs);
2706 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
2707 0 /*expectedFlags*/);
2708}
2709
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002710/**
2711 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
2712 * the device default right away. In the test scenario, we check both the default value,
2713 * and the action of enabling / disabling.
2714 */
2715TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07002716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002717 sp<FakeWindowHandle> window =
2718 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2719
2720 // Set focused application.
2721 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002722 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002723
2724 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00002725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002726 setFocusedWindow(window);
2727
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002728 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2729
2730 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002731 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002732 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002733 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
2734
2735 SCOPED_TRACE("Disable touch mode");
2736 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07002737 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002739 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002740 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
2741
2742 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002743 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002744 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002745 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
2746
2747 SCOPED_TRACE("Enable touch mode again");
2748 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07002749 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002751 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002752 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2753
2754 window->assertNoEvents();
2755}
2756
Gang Wange9087892020-01-07 12:17:14 -05002757TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002758 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05002759 sp<FakeWindowHandle> window =
2760 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2761
2762 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002763 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05002764
Arthur Hung72d8dc32020-03-28 00:48:39 +00002765 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002766 setFocusedWindow(window);
2767
Gang Wange9087892020-01-07 12:17:14 -05002768 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2769
2770 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2771 mDispatcher->notifyKey(&keyArgs);
2772
2773 InputEvent* event = window->consume();
2774 ASSERT_NE(event, nullptr);
2775
2776 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2777 ASSERT_NE(verified, nullptr);
2778 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
2779
2780 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
2781 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
2782 ASSERT_EQ(keyArgs.source, verified->source);
2783 ASSERT_EQ(keyArgs.displayId, verified->displayId);
2784
2785 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
2786
2787 ASSERT_EQ(keyArgs.action, verifiedKey.action);
2788 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05002789 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
2790 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
2791 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
2792 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
2793 ASSERT_EQ(0, verifiedKey.repeatCount);
2794}
2795
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002796TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002797 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002798 sp<FakeWindowHandle> window =
2799 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2800
2801 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2802
Arthur Hung72d8dc32020-03-28 00:48:39 +00002803 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002804
2805 NotifyMotionArgs motionArgs =
2806 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2807 ADISPLAY_ID_DEFAULT);
2808 mDispatcher->notifyMotion(&motionArgs);
2809
2810 InputEvent* event = window->consume();
2811 ASSERT_NE(event, nullptr);
2812
2813 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2814 ASSERT_NE(verified, nullptr);
2815 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2816
2817 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2818 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2819 EXPECT_EQ(motionArgs.source, verified->source);
2820 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2821
2822 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2823
2824 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2825 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2826 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2827 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2828 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2829 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2830 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2831}
2832
Prabir Pradhan664834b2021-05-20 16:00:42 -07002833TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickAndTouchpadNotTransformed) {
yunho.shinf4a80b82020-11-16 21:13:57 +09002834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2835 sp<FakeWindowHandle> window =
2836 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2837 const std::string name = window->getName();
2838
2839 // Window gets transformed by offset values.
2840 window->setWindowOffset(500.0f, 500.0f);
2841
2842 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2843 window->setFocusable(true);
2844
2845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2846
2847 // First, we set focused window so that focusedWindowHandle is not null.
2848 setFocusedWindow(window);
2849
2850 // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
2851 window->consumeFocusEvent(true);
2852
Prabir Pradhan664834b2021-05-20 16:00:42 -07002853 constexpr const std::array nonTransformedSources = {std::pair(AINPUT_SOURCE_TOUCHPAD,
2854 AMOTION_EVENT_ACTION_DOWN),
2855 std::pair(AINPUT_SOURCE_JOYSTICK,
2856 AMOTION_EVENT_ACTION_MOVE)};
2857 for (const auto& [source, action] : nonTransformedSources) {
2858 const NotifyMotionArgs motionArgs = generateMotionArgs(action, source, ADISPLAY_ID_DEFAULT);
Prabir Pradhanbd527712021-03-09 19:17:09 -08002859 mDispatcher->notifyMotion(&motionArgs);
yunho.shinf4a80b82020-11-16 21:13:57 +09002860
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002861 MotionEvent* event = window->consumeMotion();
Prabir Pradhanbd527712021-03-09 19:17:09 -08002862 ASSERT_NE(event, nullptr);
yunho.shinf4a80b82020-11-16 21:13:57 +09002863
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002864 const MotionEvent& motionEvent = *event;
Prabir Pradhan664834b2021-05-20 16:00:42 -07002865 EXPECT_EQ(action, motionEvent.getAction());
Prabir Pradhanbd527712021-03-09 19:17:09 -08002866 EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
yunho.shinf4a80b82020-11-16 21:13:57 +09002867
Prabir Pradhanbd527712021-03-09 19:17:09 -08002868 float expectedX = motionArgs.pointerCoords[0].getX();
2869 float expectedY = motionArgs.pointerCoords[0].getY();
yunho.shinf4a80b82020-11-16 21:13:57 +09002870
Prabir Pradhanbd527712021-03-09 19:17:09 -08002871 // Ensure the axis values from the final motion event are not transformed.
2872 EXPECT_EQ(expectedX, motionEvent.getX(0))
2873 << "expected " << expectedX << " for x coord of " << name.c_str() << ", got "
2874 << motionEvent.getX(0);
2875 EXPECT_EQ(expectedY, motionEvent.getY(0))
2876 << "expected " << expectedY << " for y coord of " << name.c_str() << ", got "
2877 << motionEvent.getY(0);
2878 // Ensure the raw and transformed axis values for the motion event are the same.
2879 EXPECT_EQ(motionEvent.getRawX(0), motionEvent.getX(0))
2880 << "expected raw and transformed X-axis values to be equal";
2881 EXPECT_EQ(motionEvent.getRawY(0), motionEvent.getY(0))
2882 << "expected raw and transformed Y-axis values to be equal";
2883 }
yunho.shinf4a80b82020-11-16 21:13:57 +09002884}
2885
chaviw09c8d2d2020-08-24 15:48:26 -07002886/**
2887 * Ensure that separate calls to sign the same data are generating the same key.
2888 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2889 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2890 * tests.
2891 */
2892TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2893 KeyEvent event = getTestKeyEvent();
2894 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2895
2896 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2897 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2898 ASSERT_EQ(hmac1, hmac2);
2899}
2900
2901/**
2902 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2903 */
2904TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2905 KeyEvent event = getTestKeyEvent();
2906 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2907 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2908
2909 verifiedEvent.deviceId += 1;
2910 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2911
2912 verifiedEvent.source += 1;
2913 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2914
2915 verifiedEvent.eventTimeNanos += 1;
2916 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2917
2918 verifiedEvent.displayId += 1;
2919 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2920
2921 verifiedEvent.action += 1;
2922 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2923
2924 verifiedEvent.downTimeNanos += 1;
2925 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2926
2927 verifiedEvent.flags += 1;
2928 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2929
2930 verifiedEvent.keyCode += 1;
2931 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2932
2933 verifiedEvent.scanCode += 1;
2934 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2935
2936 verifiedEvent.metaState += 1;
2937 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2938
2939 verifiedEvent.repeatCount += 1;
2940 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2941}
2942
Vishnu Nair958da932020-08-21 17:12:37 -07002943TEST_F(InputDispatcherTest, SetFocusedWindow) {
2944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2945 sp<FakeWindowHandle> windowTop =
2946 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2947 sp<FakeWindowHandle> windowSecond =
2948 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2949 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2950
2951 // Top window is also focusable but is not granted focus.
2952 windowTop->setFocusable(true);
2953 windowSecond->setFocusable(true);
2954 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2955 setFocusedWindow(windowSecond);
2956
2957 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2959 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002960
2961 // Focused window should receive event.
2962 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2963 windowTop->assertNoEvents();
2964}
2965
2966TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2967 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2968 sp<FakeWindowHandle> window =
2969 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2970 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2971
2972 window->setFocusable(true);
2973 // Release channel for window is no longer valid.
2974 window->releaseChannel();
2975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2976 setFocusedWindow(window);
2977
2978 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002979 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2980 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002981
2982 // window channel is invalid, so it should not receive any input event.
2983 window->assertNoEvents();
2984}
2985
2986TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2987 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2988 sp<FakeWindowHandle> window =
2989 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2990 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2991
2992 // Window is not focusable.
2993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2994 setFocusedWindow(window);
2995
2996 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002997 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2998 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002999
3000 // window is invalid, so it should not receive any input event.
3001 window->assertNoEvents();
3002}
3003
3004TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
3005 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3006 sp<FakeWindowHandle> windowTop =
3007 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3008 sp<FakeWindowHandle> windowSecond =
3009 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3010 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3011
3012 windowTop->setFocusable(true);
3013 windowSecond->setFocusable(true);
3014 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3015 setFocusedWindow(windowTop);
3016 windowTop->consumeFocusEvent(true);
3017
3018 setFocusedWindow(windowSecond, windowTop);
3019 windowSecond->consumeFocusEvent(true);
3020 windowTop->consumeFocusEvent(false);
3021
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3023 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003024
3025 // Focused window should receive event.
3026 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3027}
3028
3029TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
3030 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3031 sp<FakeWindowHandle> windowTop =
3032 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3033 sp<FakeWindowHandle> windowSecond =
3034 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3035 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3036
3037 windowTop->setFocusable(true);
3038 windowSecond->setFocusable(true);
3039 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3040 setFocusedWindow(windowSecond, windowTop);
3041
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003042 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3043 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003044
3045 // Event should be dropped.
3046 windowTop->assertNoEvents();
3047 windowSecond->assertNoEvents();
3048}
3049
3050TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
3051 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3052 sp<FakeWindowHandle> window =
3053 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3054 sp<FakeWindowHandle> previousFocusedWindow =
3055 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
3056 ADISPLAY_ID_DEFAULT);
3057 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3058
3059 window->setFocusable(true);
3060 previousFocusedWindow->setFocusable(true);
3061 window->setVisible(false);
3062 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
3063 setFocusedWindow(previousFocusedWindow);
3064 previousFocusedWindow->consumeFocusEvent(true);
3065
3066 // Requesting focus on invisible window takes focus from currently focused window.
3067 setFocusedWindow(window);
3068 previousFocusedWindow->consumeFocusEvent(false);
3069
3070 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003072 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003073 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003074
3075 // Window does not get focus event or key down.
3076 window->assertNoEvents();
3077
3078 // Window becomes visible.
3079 window->setVisible(true);
3080 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3081
3082 // Window receives focus event.
3083 window->consumeFocusEvent(true);
3084 // Focused window receives key down.
3085 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3086}
3087
Vishnu Nair599f1412021-06-21 10:39:58 -07003088TEST_F(InputDispatcherTest, DisplayRemoved) {
3089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3090 sp<FakeWindowHandle> window =
3091 new FakeWindowHandle(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
3092 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3093
3094 // window is granted focus.
3095 window->setFocusable(true);
3096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3097 setFocusedWindow(window);
3098 window->consumeFocusEvent(true);
3099
3100 // When a display is removed window loses focus.
3101 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
3102 window->consumeFocusEvent(false);
3103}
3104
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003105/**
3106 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
3107 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
3108 * of the 'slipperyEnterWindow'.
3109 *
3110 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
3111 * a way so that the touched location is no longer covered by the top window.
3112 *
3113 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
3114 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
3115 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
3116 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
3117 * with ACTION_DOWN).
3118 * Thus, the touch has been transferred from the top window into the bottom window, because the top
3119 * window moved itself away from the touched location and had Flag::SLIPPERY.
3120 *
3121 * Even though the top window moved away from the touched location, it is still obscuring the bottom
3122 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
3123 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
3124 *
3125 * In this test, we ensure that the event received by the bottom window has
3126 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
3127 */
3128TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
3129 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
3130 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
3131
3132 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3133 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3134
3135 sp<FakeWindowHandle> slipperyExitWindow =
3136 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviw3277faf2021-05-19 16:45:23 -05003137 slipperyExitWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SLIPPERY);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003138 // Make sure this one overlaps the bottom window
3139 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
3140 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
3141 // one. Windows with the same owner are not considered to be occluding each other.
3142 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
3143
3144 sp<FakeWindowHandle> slipperyEnterWindow =
3145 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3146 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
3147
3148 mDispatcher->setInputWindows(
3149 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3150
3151 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
3152 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3153 ADISPLAY_ID_DEFAULT, {{50, 50}});
3154 mDispatcher->notifyMotion(&args);
3155 slipperyExitWindow->consumeMotionDown();
3156 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
3157 mDispatcher->setInputWindows(
3158 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3159
3160 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3161 ADISPLAY_ID_DEFAULT, {{51, 51}});
3162 mDispatcher->notifyMotion(&args);
3163
3164 slipperyExitWindow->consumeMotionCancel();
3165
3166 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
3167 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
3168}
3169
Garfield Tan1c7bc862020-01-28 13:24:04 -08003170class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
3171protected:
3172 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
3173 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
3174
Chris Yea209fde2020-07-22 13:54:51 -07003175 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003176 sp<FakeWindowHandle> mWindow;
3177
3178 virtual void SetUp() override {
3179 mFakePolicy = new FakeInputDispatcherPolicy();
3180 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
3181 mDispatcher = new InputDispatcher(mFakePolicy);
3182 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
3183 ASSERT_EQ(OK, mDispatcher->start());
3184
3185 setUpWindow();
3186 }
3187
3188 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07003189 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08003190 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
3191
Vishnu Nair47074b82020-08-14 11:54:47 -07003192 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003193 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003194 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003195 mWindow->consumeFocusEvent(true);
3196 }
3197
Chris Ye2ad95392020-09-01 13:44:44 -07003198 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003199 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003200 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003201 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
3202 mDispatcher->notifyKey(&keyArgs);
3203
3204 // Window should receive key down event.
3205 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3206 }
3207
3208 void expectKeyRepeatOnce(int32_t repeatCount) {
3209 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
3210 InputEvent* repeatEvent = mWindow->consume();
3211 ASSERT_NE(nullptr, repeatEvent);
3212
3213 uint32_t eventType = repeatEvent->getType();
3214 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
3215
3216 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
3217 uint32_t eventAction = repeatKeyEvent->getAction();
3218 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
3219 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
3220 }
3221
Chris Ye2ad95392020-09-01 13:44:44 -07003222 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003223 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003224 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003225 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
3226 mDispatcher->notifyKey(&keyArgs);
3227
3228 // Window should receive key down event.
3229 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
3230 0 /*expectedFlags*/);
3231 }
3232};
3233
3234TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07003235 sendAndConsumeKeyDown(1 /* deviceId */);
3236 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3237 expectKeyRepeatOnce(repeatCount);
3238 }
3239}
3240
3241TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
3242 sendAndConsumeKeyDown(1 /* deviceId */);
3243 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3244 expectKeyRepeatOnce(repeatCount);
3245 }
3246 sendAndConsumeKeyDown(2 /* deviceId */);
3247 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08003248 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3249 expectKeyRepeatOnce(repeatCount);
3250 }
3251}
3252
3253TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07003254 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003255 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07003256 sendAndConsumeKeyUp(1 /* deviceId */);
3257 mWindow->assertNoEvents();
3258}
3259
3260TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
3261 sendAndConsumeKeyDown(1 /* deviceId */);
3262 expectKeyRepeatOnce(1 /*repeatCount*/);
3263 sendAndConsumeKeyDown(2 /* deviceId */);
3264 expectKeyRepeatOnce(1 /*repeatCount*/);
3265 // Stale key up from device 1.
3266 sendAndConsumeKeyUp(1 /* deviceId */);
3267 // Device 2 is still down, keep repeating
3268 expectKeyRepeatOnce(2 /*repeatCount*/);
3269 expectKeyRepeatOnce(3 /*repeatCount*/);
3270 // Device 2 key up
3271 sendAndConsumeKeyUp(2 /* deviceId */);
3272 mWindow->assertNoEvents();
3273}
3274
3275TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
3276 sendAndConsumeKeyDown(1 /* deviceId */);
3277 expectKeyRepeatOnce(1 /*repeatCount*/);
3278 sendAndConsumeKeyDown(2 /* deviceId */);
3279 expectKeyRepeatOnce(1 /*repeatCount*/);
3280 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
3281 sendAndConsumeKeyUp(2 /* deviceId */);
3282 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08003283 mWindow->assertNoEvents();
3284}
3285
liushenxiang42232912021-05-21 20:24:09 +08003286TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
3287 sendAndConsumeKeyDown(DEVICE_ID);
3288 expectKeyRepeatOnce(1 /*repeatCount*/);
3289 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
3290 mDispatcher->notifyDeviceReset(&args);
3291 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
3292 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
3293 mWindow->assertNoEvents();
3294}
3295
Garfield Tan1c7bc862020-01-28 13:24:04 -08003296TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07003297 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003298 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3299 InputEvent* repeatEvent = mWindow->consume();
3300 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3301 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
3302 IdGenerator::getSource(repeatEvent->getId()));
3303 }
3304}
3305
3306TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07003307 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003308
3309 std::unordered_set<int32_t> idSet;
3310 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3311 InputEvent* repeatEvent = mWindow->consume();
3312 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3313 int32_t id = repeatEvent->getId();
3314 EXPECT_EQ(idSet.end(), idSet.find(id));
3315 idSet.insert(id);
3316 }
3317}
3318
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003319/* Test InputDispatcher for MultiDisplay */
3320class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
3321public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003322 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003323 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08003324
Chris Yea209fde2020-07-22 13:54:51 -07003325 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003326 windowInPrimary =
3327 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003328
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003329 // Set focus window for primary display, but focused display would be second one.
3330 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07003331 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003332 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003333 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003334 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08003335
Chris Yea209fde2020-07-22 13:54:51 -07003336 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003337 windowInSecondary =
3338 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003339 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003340 // Set focus display to second one.
3341 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
3342 // Set focus window for second display.
3343 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07003344 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003345 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003346 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003347 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003348 }
3349
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003350 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003351 InputDispatcherTest::TearDown();
3352
Chris Yea209fde2020-07-22 13:54:51 -07003353 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003354 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07003355 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003356 windowInSecondary.clear();
3357 }
3358
3359protected:
Chris Yea209fde2020-07-22 13:54:51 -07003360 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003361 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07003362 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003363 sp<FakeWindowHandle> windowInSecondary;
3364};
3365
3366TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
3367 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3369 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3370 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003371 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08003372 windowInSecondary->assertNoEvents();
3373
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003374 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3376 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3377 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003378 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003379 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08003380}
3381
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003382TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08003383 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3385 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003386 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003387 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08003388 windowInSecondary->assertNoEvents();
3389
3390 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003391 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003392 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003393 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003394 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08003395
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003396 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003397 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08003398
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003399 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003400 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
3401 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08003402
3403 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003404 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003405 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08003406 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003407 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08003408 windowInSecondary->assertNoEvents();
3409}
3410
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003411// Test per-display input monitors for motion event.
3412TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08003413 FakeMonitorReceiver monitorInPrimary =
3414 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3415 FakeMonitorReceiver monitorInSecondary =
3416 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003417
3418 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3420 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3421 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003422 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003423 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003424 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003425 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003426
3427 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3429 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003431 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003432 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003433 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08003434 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003435
3436 // Test inject a non-pointer motion event.
3437 // If specific a display, it will dispatch to the focused window of particular display,
3438 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3440 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
3441 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003442 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003443 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003444 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003445 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003446}
3447
3448// Test per-display input monitors for key event.
3449TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003450 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08003451 FakeMonitorReceiver monitorInPrimary =
3452 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3453 FakeMonitorReceiver monitorInSecondary =
3454 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003455
3456 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3458 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003459 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003460 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003461 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003462 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003463}
3464
Vishnu Nair958da932020-08-21 17:12:37 -07003465TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
3466 sp<FakeWindowHandle> secondWindowInPrimary =
3467 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
3468 secondWindowInPrimary->setFocusable(true);
3469 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
3470 setFocusedWindow(secondWindowInPrimary);
3471 windowInPrimary->consumeFocusEvent(false);
3472 secondWindowInPrimary->consumeFocusEvent(true);
3473
3474 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
3476 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003477 windowInPrimary->assertNoEvents();
3478 windowInSecondary->assertNoEvents();
3479 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3480}
3481
Jackal Guof9696682018-10-05 12:23:23 +08003482class InputFilterTest : public InputDispatcherTest {
3483protected:
Jackal Guof9696682018-10-05 12:23:23 +08003484 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
3485 NotifyMotionArgs motionArgs;
3486
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003487 motionArgs =
3488 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003489 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003490 motionArgs =
3491 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003492 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003493 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003494 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003495 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003496 } else {
3497 mFakePolicy->assertFilterInputEventWasNotCalled();
3498 }
3499 }
3500
3501 void testNotifyKey(bool expectToBeFiltered) {
3502 NotifyKeyArgs keyArgs;
3503
3504 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3505 mDispatcher->notifyKey(&keyArgs);
3506 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
3507 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003508 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003509
3510 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003511 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003512 } else {
3513 mFakePolicy->assertFilterInputEventWasNotCalled();
3514 }
3515 }
3516};
3517
3518// Test InputFilter for MotionEvent
3519TEST_F(InputFilterTest, MotionEvent_InputFilter) {
3520 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
3521 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3522 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3523
3524 // Enable InputFilter
3525 mDispatcher->setInputFilterEnabled(true);
3526 // Test touch on both primary and second display, and check if both events are filtered.
3527 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
3528 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
3529
3530 // Disable InputFilter
3531 mDispatcher->setInputFilterEnabled(false);
3532 // Test touch on both primary and second display, and check if both events aren't filtered.
3533 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3534 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3535}
3536
3537// Test InputFilter for KeyEvent
3538TEST_F(InputFilterTest, KeyEvent_InputFilter) {
3539 // Since the InputFilter is disabled by default, check if key event aren't filtered.
3540 testNotifyKey(/*expectToBeFiltered*/ false);
3541
3542 // Enable InputFilter
3543 mDispatcher->setInputFilterEnabled(true);
3544 // Send a key event, and check if it is filtered.
3545 testNotifyKey(/*expectToBeFiltered*/ true);
3546
3547 // Disable InputFilter
3548 mDispatcher->setInputFilterEnabled(false);
3549 // Send a key event, and check if it isn't filtered.
3550 testNotifyKey(/*expectToBeFiltered*/ false);
3551}
3552
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003553class InputFilterInjectionPolicyTest : public InputDispatcherTest {
3554protected:
3555 virtual void SetUp() override {
3556 InputDispatcherTest::SetUp();
3557
3558 /**
3559 * We don't need to enable input filter to test the injected event policy, but we enabled it
3560 * here to make the tests more realistic, since this policy only matters when inputfilter is
3561 * on.
3562 */
3563 mDispatcher->setInputFilterEnabled(true);
3564
3565 std::shared_ptr<InputApplicationHandle> application =
3566 std::make_shared<FakeApplicationHandle>();
3567 mWindow =
3568 new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT);
3569
3570 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3571 mWindow->setFocusable(true);
3572 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3573 setFocusedWindow(mWindow);
3574 mWindow->consumeFocusEvent(true);
3575 }
3576
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003577 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3578 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003579 KeyEvent event;
3580
3581 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3582 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
3583 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
3584 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
3585 const int32_t additionalPolicyFlags =
3586 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
3587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3588 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3589 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3590 policyFlags | additionalPolicyFlags));
3591
3592 InputEvent* received = mWindow->consume();
3593 ASSERT_NE(nullptr, received);
3594 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003595 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
3596 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
3597 ASSERT_EQ(flags, keyEvent.getFlags());
3598 }
3599
3600 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3601 int32_t flags) {
3602 MotionEvent event;
3603 PointerProperties pointerProperties[1];
3604 PointerCoords pointerCoords[1];
3605 pointerProperties[0].clear();
3606 pointerProperties[0].id = 0;
3607 pointerCoords[0].clear();
3608 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
3609 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
3610
3611 ui::Transform identityTransform;
3612 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3613 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
3614 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
3615 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
3616 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07003617 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07003618 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003619 /*pointerCount*/ 1, pointerProperties, pointerCoords);
3620
3621 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
3622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3623 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3624 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3625 policyFlags | additionalPolicyFlags));
3626
3627 InputEvent* received = mWindow->consume();
3628 ASSERT_NE(nullptr, received);
3629 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
3630 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
3631 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
3632 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003633 }
3634
3635private:
3636 sp<FakeWindowHandle> mWindow;
3637};
3638
3639TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003640 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
3641 // filter. Without it, the event will no different from a regularly injected event, and the
3642 // injected device id will be overwritten.
3643 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3644 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003645}
3646
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003647TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003648 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003649 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3650 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3651}
3652
3653TEST_F(InputFilterInjectionPolicyTest,
3654 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
3655 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
3656 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3657 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003658}
3659
3660TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
3661 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003662 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003663}
3664
chaviwfd6d3512019-03-25 13:23:49 -07003665class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003666 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07003667 InputDispatcherTest::SetUp();
3668
Chris Yea209fde2020-07-22 13:54:51 -07003669 std::shared_ptr<FakeApplicationHandle> application =
3670 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003671 mUnfocusedWindow =
3672 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003673 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3674 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3675 // window.
chaviw3277faf2021-05-19 16:45:23 -05003676 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003677
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003678 mFocusedWindow =
3679 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3680 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05003681 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003682
3683 // Set focused application.
3684 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003685 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07003686
3687 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003688 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003689 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003690 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07003691 }
3692
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003693 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07003694 InputDispatcherTest::TearDown();
3695
3696 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003697 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07003698 }
3699
3700protected:
3701 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003702 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003703 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07003704};
3705
3706// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3707// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
3708// the onPointerDownOutsideFocus callback.
3709TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003711 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3712 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003714 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003715
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003716 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07003717 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
3718}
3719
3720// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
3721// DOWN on the window that doesn't have focus. Ensure no window received the
3722// onPointerDownOutsideFocus callback.
3723TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003725 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003727 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003728
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003729 ASSERT_TRUE(mDispatcher->waitForIdle());
3730 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003731}
3732
3733// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
3734// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
3735TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3737 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003738 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003739 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003740
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003741 ASSERT_TRUE(mDispatcher->waitForIdle());
3742 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003743}
3744
3745// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3746// DOWN on the window that already has focus. Ensure no window received the
3747// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003748TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003750 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003751 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003753 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003754
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003755 ASSERT_TRUE(mDispatcher->waitForIdle());
3756 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003757}
3758
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08003759// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
3760// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
3761TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
3762 const MotionEvent event =
3763 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3764 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
3765 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
3766 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
3767 .build();
3768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
3769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3770 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
3771
3772 ASSERT_TRUE(mDispatcher->waitForIdle());
3773 mFakePolicy->assertOnPointerDownWasNotCalled();
3774 // Ensure that the unfocused window did not receive any FOCUS events.
3775 mUnfocusedWindow->assertNoEvents();
3776}
3777
chaviwaf87b3e2019-10-01 16:59:28 -07003778// These tests ensures we can send touch events to a single client when there are multiple input
3779// windows that point to the same client token.
3780class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
3781 virtual void SetUp() override {
3782 InputDispatcherTest::SetUp();
3783
Chris Yea209fde2020-07-22 13:54:51 -07003784 std::shared_ptr<FakeApplicationHandle> application =
3785 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07003786 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
3787 ADISPLAY_ID_DEFAULT);
3788 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
3789 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
chaviw3277faf2021-05-19 16:45:23 -05003790 mWindow1->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003791 mWindow1->setFrame(Rect(0, 0, 100, 100));
3792
3793 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
3794 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviw3277faf2021-05-19 16:45:23 -05003795 mWindow2->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003796 mWindow2->setFrame(Rect(100, 100, 200, 200));
3797
Arthur Hung72d8dc32020-03-28 00:48:39 +00003798 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07003799 }
3800
3801protected:
3802 sp<FakeWindowHandle> mWindow1;
3803 sp<FakeWindowHandle> mWindow2;
3804
3805 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05003806 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07003807 vec2 vals = windowInfo->transform.transform(point.x, point.y);
3808 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07003809 }
3810
3811 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
3812 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003813 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07003814 InputEvent* event = window->consume();
3815
3816 ASSERT_NE(nullptr, event) << name.c_str()
3817 << ": consumer should have returned non-NULL event.";
3818
3819 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
3820 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
3821 << " event, got " << inputEventTypeToString(event->getType()) << " event";
3822
3823 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003824 assertMotionAction(expectedAction, motionEvent.getAction());
chaviwaf87b3e2019-10-01 16:59:28 -07003825
3826 for (size_t i = 0; i < points.size(); i++) {
3827 float expectedX = points[i].x;
3828 float expectedY = points[i].y;
3829
3830 EXPECT_EQ(expectedX, motionEvent.getX(i))
3831 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
3832 << ", got " << motionEvent.getX(i);
3833 EXPECT_EQ(expectedY, motionEvent.getY(i))
3834 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
3835 << ", got " << motionEvent.getY(i);
3836 }
3837 }
chaviw9eaa22c2020-07-01 16:21:27 -07003838
3839 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
3840 std::vector<PointF> expectedPoints) {
3841 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
3842 ADISPLAY_ID_DEFAULT, touchedPoints);
3843 mDispatcher->notifyMotion(&motionArgs);
3844
3845 // Always consume from window1 since it's the window that has the InputReceiver
3846 consumeMotionEvent(mWindow1, action, expectedPoints);
3847 }
chaviwaf87b3e2019-10-01 16:59:28 -07003848};
3849
3850TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
3851 // Touch Window 1
3852 PointF touchedPoint = {10, 10};
3853 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003854 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003855
3856 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003857 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003858
3859 // Touch Window 2
3860 touchedPoint = {150, 150};
3861 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003862 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003863}
3864
chaviw9eaa22c2020-07-01 16:21:27 -07003865TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
3866 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07003867 mWindow2->setWindowScale(0.5f, 0.5f);
3868
3869 // Touch Window 1
3870 PointF touchedPoint = {10, 10};
3871 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003872 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003873 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003874 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003875
3876 // Touch Window 2
3877 touchedPoint = {150, 150};
3878 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003879 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
3880 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003881
chaviw9eaa22c2020-07-01 16:21:27 -07003882 // Update the transform so rotation is set
3883 mWindow2->setWindowTransform(0, -1, 1, 0);
3884 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
3885 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003886}
3887
chaviw9eaa22c2020-07-01 16:21:27 -07003888TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003889 mWindow2->setWindowScale(0.5f, 0.5f);
3890
3891 // Touch Window 1
3892 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3893 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003894 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003895
3896 // Touch Window 2
3897 int32_t actionPointerDown =
3898 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003899 touchedPoints.push_back(PointF{150, 150});
3900 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3901 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003902
chaviw9eaa22c2020-07-01 16:21:27 -07003903 // Release Window 2
3904 int32_t actionPointerUp =
3905 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3906 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3907 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003908
chaviw9eaa22c2020-07-01 16:21:27 -07003909 // Update the transform so rotation is set for Window 2
3910 mWindow2->setWindowTransform(0, -1, 1, 0);
3911 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3912 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003913}
3914
chaviw9eaa22c2020-07-01 16:21:27 -07003915TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003916 mWindow2->setWindowScale(0.5f, 0.5f);
3917
3918 // Touch Window 1
3919 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3920 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003921 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003922
3923 // Touch Window 2
3924 int32_t actionPointerDown =
3925 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003926 touchedPoints.push_back(PointF{150, 150});
3927 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003928
chaviw9eaa22c2020-07-01 16:21:27 -07003929 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003930
3931 // Move both windows
3932 touchedPoints = {{20, 20}, {175, 175}};
3933 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3934 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3935
chaviw9eaa22c2020-07-01 16:21:27 -07003936 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003937
chaviw9eaa22c2020-07-01 16:21:27 -07003938 // Release Window 2
3939 int32_t actionPointerUp =
3940 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3941 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3942 expectedPoints.pop_back();
3943
3944 // Touch Window 2
3945 mWindow2->setWindowTransform(0, -1, 1, 0);
3946 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3947 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
3948
3949 // Move both windows
3950 touchedPoints = {{20, 20}, {175, 175}};
3951 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3952 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3953
3954 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003955}
3956
3957TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
3958 mWindow1->setWindowScale(0.5f, 0.5f);
3959
3960 // Touch Window 1
3961 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3962 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003963 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003964
3965 // Touch Window 2
3966 int32_t actionPointerDown =
3967 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003968 touchedPoints.push_back(PointF{150, 150});
3969 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003970
chaviw9eaa22c2020-07-01 16:21:27 -07003971 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003972
3973 // Move both windows
3974 touchedPoints = {{20, 20}, {175, 175}};
3975 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3976 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3977
chaviw9eaa22c2020-07-01 16:21:27 -07003978 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003979}
3980
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003981class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
3982 virtual void SetUp() override {
3983 InputDispatcherTest::SetUp();
3984
Chris Yea209fde2020-07-22 13:54:51 -07003985 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003986 mApplication->setDispatchingTimeout(20ms);
3987 mWindow =
3988 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3989 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003990 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07003991 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003992 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3993 // window.
chaviw3277faf2021-05-19 16:45:23 -05003994 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003995
3996 // Set focused application.
3997 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
3998
3999 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004000 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004001 mWindow->consumeFocusEvent(true);
4002 }
4003
4004 virtual void TearDown() override {
4005 InputDispatcherTest::TearDown();
4006 mWindow.clear();
4007 }
4008
4009protected:
Chris Yea209fde2020-07-22 13:54:51 -07004010 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004011 sp<FakeWindowHandle> mWindow;
4012 static constexpr PointF WINDOW_LOCATION = {20, 20};
4013
4014 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004016 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4017 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004019 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4020 WINDOW_LOCATION));
4021 }
4022};
4023
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004024// Send a tap and respond, which should not cause an ANR.
4025TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
4026 tapOnWindow();
4027 mWindow->consumeMotionDown();
4028 mWindow->consumeMotionUp();
4029 ASSERT_TRUE(mDispatcher->waitForIdle());
4030 mFakePolicy->assertNotifyAnrWasNotCalled();
4031}
4032
4033// Send a regular key and respond, which should not cause an ANR.
4034TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004036 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4037 ASSERT_TRUE(mDispatcher->waitForIdle());
4038 mFakePolicy->assertNotifyAnrWasNotCalled();
4039}
4040
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004041TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
4042 mWindow->setFocusable(false);
4043 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4044 mWindow->consumeFocusEvent(false);
4045
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004046 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004047 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004048 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4049 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004051 // Key will not go to window because we have no focused window.
4052 // The 'no focused window' ANR timer should start instead.
4053
4054 // Now, the focused application goes away.
4055 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
4056 // The key should get dropped and there should be no ANR.
4057
4058 ASSERT_TRUE(mDispatcher->waitForIdle());
4059 mFakePolicy->assertNotifyAnrWasNotCalled();
4060}
4061
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004062// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004063// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
4064// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004065TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004067 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4068 WINDOW_LOCATION));
4069
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004070 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
4071 ASSERT_TRUE(sequenceNum);
4072 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004073 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004074
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004075 mWindow->finishEvent(*sequenceNum);
4076 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4077 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004078 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004079 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004080}
4081
4082// Send a key to the app and have the app not respond right away.
4083TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
4084 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004086 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
4087 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004088 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004089 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004090 ASSERT_TRUE(mDispatcher->waitForIdle());
4091}
4092
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004093// We have a focused application, but no focused window
4094TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004095 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4097 mWindow->consumeFocusEvent(false);
4098
4099 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004101 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4102 WINDOW_LOCATION));
4103 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
4104 mDispatcher->waitForIdle();
4105 mFakePolicy->assertNotifyAnrWasNotCalled();
4106
4107 // Once a focused event arrives, we get an ANR for this application
4108 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4109 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004110 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004111 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004112 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004113 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004114 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004115 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004116 ASSERT_TRUE(mDispatcher->waitForIdle());
4117}
4118
4119// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004120// Make sure that we don't notify policy twice about the same ANR.
4121TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004122 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004123 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4124 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004125
4126 // Once a focused event arrives, we get an ANR for this application
4127 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4128 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004129 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004130 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004131 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004132 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004133 const std::chrono::duration appTimeout =
4134 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004135 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004136
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004137 std::this_thread::sleep_for(appTimeout);
4138 // ANR should not be raised again. It is up to policy to do that if it desires.
4139 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004140
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004141 // If we now get a focused window, the ANR should stop, but the policy handles that via
4142 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004143 ASSERT_TRUE(mDispatcher->waitForIdle());
4144}
4145
4146// We have a focused application, but no focused window
4147TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004148 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004149 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4150 mWindow->consumeFocusEvent(false);
4151
4152 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004153 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004154 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004155 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4156 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004157
4158 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004159 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004160
4161 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004162 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004163 ASSERT_TRUE(mDispatcher->waitForIdle());
4164 mWindow->assertNoEvents();
4165}
4166
4167/**
4168 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
4169 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
4170 * If we process 1 of the events, but ANR on the second event with the same timestamp,
4171 * the ANR mechanism should still work.
4172 *
4173 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
4174 * DOWN event, while not responding on the second one.
4175 */
4176TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
4177 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
4178 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4179 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4180 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4181 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004182 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004183
4184 // Now send ACTION_UP, with identical timestamp
4185 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4186 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4187 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4188 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004189 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004190
4191 // We have now sent down and up. Let's consume first event and then ANR on the second.
4192 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4193 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004194 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004195}
4196
4197// If an app is not responding to a key event, gesture monitors should continue to receive
4198// new motion events
4199TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
4200 FakeMonitorReceiver monitor =
4201 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
4202 true /*isGestureMonitor*/);
4203
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4205 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004206 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004208
4209 // Stuck on the ACTION_UP
4210 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004211 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004212
4213 // New tap will go to the gesture monitor, but not to the window
4214 tapOnWindow();
4215 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4216 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4217
4218 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4219 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004220 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004221 mWindow->assertNoEvents();
4222 monitor.assertNoEvents();
4223}
4224
4225// If an app is not responding to a motion event, gesture monitors should continue to receive
4226// new motion events
4227TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
4228 FakeMonitorReceiver monitor =
4229 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
4230 true /*isGestureMonitor*/);
4231
4232 tapOnWindow();
4233 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4234 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4235
4236 mWindow->consumeMotionDown();
4237 // Stuck on the ACTION_UP
4238 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004239 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004240
4241 // New tap will go to the gesture monitor, but not to the window
4242 tapOnWindow();
4243 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4244 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4245
4246 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4247 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004248 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004249 mWindow->assertNoEvents();
4250 monitor.assertNoEvents();
4251}
4252
4253// If a window is unresponsive, then you get anr. if the window later catches up and starts to
4254// process events, you don't get an anr. When the window later becomes unresponsive again, you
4255// get an ANR again.
4256// 1. tap -> block on ACTION_UP -> receive ANR
4257// 2. consume all pending events (= queue becomes healthy again)
4258// 3. tap again -> block on ACTION_UP again -> receive ANR second time
4259TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
4260 tapOnWindow();
4261
4262 mWindow->consumeMotionDown();
4263 // Block on ACTION_UP
4264 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004265 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004266 mWindow->consumeMotionUp(); // Now the connection should be healthy again
4267 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004268 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004269 mWindow->assertNoEvents();
4270
4271 tapOnWindow();
4272 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004273 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004274 mWindow->consumeMotionUp();
4275
4276 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004277 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004278 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004279 mWindow->assertNoEvents();
4280}
4281
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004282// If a connection remains unresponsive for a while, make sure policy is only notified once about
4283// it.
4284TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004286 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4287 WINDOW_LOCATION));
4288
4289 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004290 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004291 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004292 // 'notifyConnectionUnresponsive' should only be called once per connection
4293 mFakePolicy->assertNotifyAnrWasNotCalled();
4294 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004295 mWindow->consumeMotionDown();
4296 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4297 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4298 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004299 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004300 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004301 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004302}
4303
4304/**
4305 * If a window is processing a motion event, and then a key event comes in, the key event should
4306 * not to to the focused window until the motion is processed.
4307 *
4308 * Warning!!!
4309 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4310 * and the injection timeout that we specify when injecting the key.
4311 * We must have the injection timeout (10ms) be smaller than
4312 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4313 *
4314 * If that value changes, this test should also change.
4315 */
4316TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
4317 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4318 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4319
4320 tapOnWindow();
4321 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4322 ASSERT_TRUE(downSequenceNum);
4323 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4324 ASSERT_TRUE(upSequenceNum);
4325 // Don't finish the events yet, and send a key
4326 // Injection will "succeed" because we will eventually give up and send the key to the focused
4327 // window even if motions are still being processed. But because the injection timeout is short,
4328 // we will receive INJECTION_TIMED_OUT as the result.
4329
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004330 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004331 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004332 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4333 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004334 // Key will not be sent to the window, yet, because the window is still processing events
4335 // and the key remains pending, waiting for the touch events to be processed
4336 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4337 ASSERT_FALSE(keySequenceNum);
4338
4339 std::this_thread::sleep_for(500ms);
4340 // if we wait long enough though, dispatcher will give up, and still send the key
4341 // to the focused window, even though we have not yet finished the motion event
4342 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4343 mWindow->finishEvent(*downSequenceNum);
4344 mWindow->finishEvent(*upSequenceNum);
4345}
4346
4347/**
4348 * If a window is processing a motion event, and then a key event comes in, the key event should
4349 * not go to the focused window until the motion is processed.
4350 * If then a new motion comes in, then the pending key event should be going to the currently
4351 * focused window right away.
4352 */
4353TEST_F(InputDispatcherSingleWindowAnr,
4354 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
4355 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4356 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4357
4358 tapOnWindow();
4359 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4360 ASSERT_TRUE(downSequenceNum);
4361 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4362 ASSERT_TRUE(upSequenceNum);
4363 // Don't finish the events yet, and send a key
4364 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004365 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004366 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004367 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004368 // At this point, key is still pending, and should not be sent to the application yet.
4369 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4370 ASSERT_FALSE(keySequenceNum);
4371
4372 // Now tap down again. It should cause the pending key to go to the focused window right away.
4373 tapOnWindow();
4374 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
4375 // the other events yet. We can finish events in any order.
4376 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
4377 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
4378 mWindow->consumeMotionDown();
4379 mWindow->consumeMotionUp();
4380 mWindow->assertNoEvents();
4381}
4382
4383class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
4384 virtual void SetUp() override {
4385 InputDispatcherTest::SetUp();
4386
Chris Yea209fde2020-07-22 13:54:51 -07004387 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004388 mApplication->setDispatchingTimeout(10ms);
4389 mUnfocusedWindow =
4390 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
4391 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
4392 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4393 // window.
4394 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
chaviw3277faf2021-05-19 16:45:23 -05004395 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL |
4396 WindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
4397 WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004398
4399 mFocusedWindow =
4400 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004401 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004402 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05004403 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004404
4405 // Set focused application.
4406 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07004407 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004408
4409 // Expect one focus window exist in display.
4410 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004411 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004412 mFocusedWindow->consumeFocusEvent(true);
4413 }
4414
4415 virtual void TearDown() override {
4416 InputDispatcherTest::TearDown();
4417
4418 mUnfocusedWindow.clear();
4419 mFocusedWindow.clear();
4420 }
4421
4422protected:
Chris Yea209fde2020-07-22 13:54:51 -07004423 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004424 sp<FakeWindowHandle> mUnfocusedWindow;
4425 sp<FakeWindowHandle> mFocusedWindow;
4426 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
4427 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
4428 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
4429
4430 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
4431
4432 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
4433
4434private:
4435 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004437 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4438 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004440 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4441 location));
4442 }
4443};
4444
4445// If we have 2 windows that are both unresponsive, the one with the shortest timeout
4446// should be ANR'd first.
4447TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004449 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4450 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004452 mFocusedWindow->consumeMotionDown();
4453 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4454 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4455 // We consumed all events, so no ANR
4456 ASSERT_TRUE(mDispatcher->waitForIdle());
4457 mFakePolicy->assertNotifyAnrWasNotCalled();
4458
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004460 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4461 FOCUSED_WINDOW_LOCATION));
4462 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
4463 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004464
4465 const std::chrono::duration timeout =
4466 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004467 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004468 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
4469 // sequence to make it consistent
4470 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004471 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004472 mFocusedWindow->consumeMotionDown();
4473 // This cancel is generated because the connection was unresponsive
4474 mFocusedWindow->consumeMotionCancel();
4475 mFocusedWindow->assertNoEvents();
4476 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004477 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004478 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004479 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004480}
4481
4482// If we have 2 windows with identical timeouts that are both unresponsive,
4483// it doesn't matter which order they should have ANR.
4484// But we should receive ANR for both.
4485TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
4486 // Set the timeout for unfocused window to match the focused window
4487 mUnfocusedWindow->setDispatchingTimeout(10ms);
4488 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4489
4490 tapOnFocusedWindow();
4491 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004492 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
4493 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004494
4495 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004496 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
4497 mFocusedWindow->getToken() == anrConnectionToken2);
4498 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
4499 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004500
4501 ASSERT_TRUE(mDispatcher->waitForIdle());
4502 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004503
4504 mFocusedWindow->consumeMotionDown();
4505 mFocusedWindow->consumeMotionUp();
4506 mUnfocusedWindow->consumeMotionOutside();
4507
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004508 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
4509 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004510
4511 // Both applications should be marked as responsive, in any order
4512 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
4513 mFocusedWindow->getToken() == responsiveToken2);
4514 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
4515 mUnfocusedWindow->getToken() == responsiveToken2);
4516 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004517}
4518
4519// If a window is already not responding, the second tap on the same window should be ignored.
4520// We should also log an error to account for the dropped event (not tested here).
4521// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
4522TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
4523 tapOnFocusedWindow();
4524 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4525 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4526 // Receive the events, but don't respond
4527 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
4528 ASSERT_TRUE(downEventSequenceNum);
4529 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
4530 ASSERT_TRUE(upEventSequenceNum);
4531 const std::chrono::duration timeout =
4532 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004533 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004534
4535 // Tap once again
4536 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004537 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004538 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4539 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004540 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004541 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4542 FOCUSED_WINDOW_LOCATION));
4543 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
4544 // valid touch target
4545 mUnfocusedWindow->assertNoEvents();
4546
4547 // Consume the first tap
4548 mFocusedWindow->finishEvent(*downEventSequenceNum);
4549 mFocusedWindow->finishEvent(*upEventSequenceNum);
4550 ASSERT_TRUE(mDispatcher->waitForIdle());
4551 // The second tap did not go to the focused window
4552 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004553 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004554 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004555 mFakePolicy->assertNotifyAnrWasNotCalled();
4556}
4557
4558// If you tap outside of all windows, there will not be ANR
4559TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004560 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004561 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4562 LOCATION_OUTSIDE_ALL_WINDOWS));
4563 ASSERT_TRUE(mDispatcher->waitForIdle());
4564 mFakePolicy->assertNotifyAnrWasNotCalled();
4565}
4566
4567// Since the focused window is paused, tapping on it should not produce any events
4568TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
4569 mFocusedWindow->setPaused(true);
4570 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4571
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004572 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004573 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4574 FOCUSED_WINDOW_LOCATION));
4575
4576 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
4577 ASSERT_TRUE(mDispatcher->waitForIdle());
4578 // Should not ANR because the window is paused, and touches shouldn't go to it
4579 mFakePolicy->assertNotifyAnrWasNotCalled();
4580
4581 mFocusedWindow->assertNoEvents();
4582 mUnfocusedWindow->assertNoEvents();
4583}
4584
4585/**
4586 * If a window is processing a motion event, and then a key event comes in, the key event should
4587 * not to to the focused window until the motion is processed.
4588 * If a different window becomes focused at this time, the key should go to that window instead.
4589 *
4590 * Warning!!!
4591 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4592 * and the injection timeout that we specify when injecting the key.
4593 * We must have the injection timeout (10ms) be smaller than
4594 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4595 *
4596 * If that value changes, this test should also change.
4597 */
4598TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
4599 // Set a long ANR timeout to prevent it from triggering
4600 mFocusedWindow->setDispatchingTimeout(2s);
4601 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4602
4603 tapOnUnfocusedWindow();
4604 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
4605 ASSERT_TRUE(downSequenceNum);
4606 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
4607 ASSERT_TRUE(upSequenceNum);
4608 // Don't finish the events yet, and send a key
4609 // Injection will succeed because we will eventually give up and send the key to the focused
4610 // window even if motions are still being processed.
4611
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004612 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004613 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004614 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
4615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004616 // Key will not be sent to the window, yet, because the window is still processing events
4617 // and the key remains pending, waiting for the touch events to be processed
4618 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
4619 ASSERT_FALSE(keySequenceNum);
4620
4621 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07004622 mFocusedWindow->setFocusable(false);
4623 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004624 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004625 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004626
4627 // Focus events should precede the key events
4628 mUnfocusedWindow->consumeFocusEvent(true);
4629 mFocusedWindow->consumeFocusEvent(false);
4630
4631 // Finish the tap events, which should unblock dispatcher
4632 mUnfocusedWindow->finishEvent(*downSequenceNum);
4633 mUnfocusedWindow->finishEvent(*upSequenceNum);
4634
4635 // Now that all queues are cleared and no backlog in the connections, the key event
4636 // can finally go to the newly focused "mUnfocusedWindow".
4637 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4638 mFocusedWindow->assertNoEvents();
4639 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004640 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004641}
4642
4643// When the touch stream is split across 2 windows, and one of them does not respond,
4644// then ANR should be raised and the touch should be canceled for the unresponsive window.
4645// The other window should not be affected by that.
4646TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
4647 // Touch Window 1
4648 NotifyMotionArgs motionArgs =
4649 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4650 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
4651 mDispatcher->notifyMotion(&motionArgs);
4652 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4653 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4654
4655 // Touch Window 2
4656 int32_t actionPointerDown =
4657 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4658
4659 motionArgs =
4660 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4661 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
4662 mDispatcher->notifyMotion(&motionArgs);
4663
4664 const std::chrono::duration timeout =
4665 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004666 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004667
4668 mUnfocusedWindow->consumeMotionDown();
4669 mFocusedWindow->consumeMotionDown();
4670 // Focused window may or may not receive ACTION_MOVE
4671 // But it should definitely receive ACTION_CANCEL due to the ANR
4672 InputEvent* event;
4673 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
4674 ASSERT_TRUE(moveOrCancelSequenceNum);
4675 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
4676 ASSERT_NE(nullptr, event);
4677 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
4678 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
4679 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
4680 mFocusedWindow->consumeMotionCancel();
4681 } else {
4682 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
4683 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004684 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004685 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004686
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004687 mUnfocusedWindow->assertNoEvents();
4688 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004689 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004690}
4691
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004692/**
4693 * If we have no focused window, and a key comes in, we start the ANR timer.
4694 * The focused application should add a focused window before the timer runs out to prevent ANR.
4695 *
4696 * If the user touches another application during this time, the key should be dropped.
4697 * Next, if a new focused window comes in, without toggling the focused application,
4698 * then no ANR should occur.
4699 *
4700 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
4701 * but in some cases the policy may not update the focused application.
4702 */
4703TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
4704 std::shared_ptr<FakeApplicationHandle> focusedApplication =
4705 std::make_shared<FakeApplicationHandle>();
4706 focusedApplication->setDispatchingTimeout(60ms);
4707 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
4708 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
4709 mFocusedWindow->setFocusable(false);
4710
4711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4712 mFocusedWindow->consumeFocusEvent(false);
4713
4714 // Send a key. The ANR timer should start because there is no focused window.
4715 // 'focusedApplication' will get blamed if this timer completes.
4716 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004717 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004718 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004719 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4720 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004721 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004722
4723 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
4724 // then the injected touches won't cause the focused event to get dropped.
4725 // The dispatcher only checks for whether the queue should be pruned upon queueing.
4726 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
4727 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
4728 // For this test, it means that the key would get delivered to the window once it becomes
4729 // focused.
4730 std::this_thread::sleep_for(10ms);
4731
4732 // Touch unfocused window. This should force the pending key to get dropped.
4733 NotifyMotionArgs motionArgs =
4734 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4735 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
4736 mDispatcher->notifyMotion(&motionArgs);
4737
4738 // We do not consume the motion right away, because that would require dispatcher to first
4739 // process (== drop) the key event, and by that time, ANR will be raised.
4740 // Set the focused window first.
4741 mFocusedWindow->setFocusable(true);
4742 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4743 setFocusedWindow(mFocusedWindow);
4744 mFocusedWindow->consumeFocusEvent(true);
4745 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
4746 // to another application. This could be a bug / behaviour in the policy.
4747
4748 mUnfocusedWindow->consumeMotionDown();
4749
4750 ASSERT_TRUE(mDispatcher->waitForIdle());
4751 // Should not ANR because we actually have a focused window. It was just added too slowly.
4752 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
4753}
4754
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004755// These tests ensure we cannot send touch events to a window that's positioned behind a window
4756// that has feature NO_INPUT_CHANNEL.
4757// Layout:
4758// Top (closest to user)
4759// mNoInputWindow (above all windows)
4760// mBottomWindow
4761// Bottom (furthest from user)
4762class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
4763 virtual void SetUp() override {
4764 InputDispatcherTest::SetUp();
4765
4766 mApplication = std::make_shared<FakeApplicationHandle>();
4767 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4768 "Window without input channel", ADISPLAY_ID_DEFAULT,
4769 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
4770
chaviw3277faf2021-05-19 16:45:23 -05004771 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004772 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4773 // It's perfectly valid for this window to not have an associated input channel
4774
4775 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
4776 ADISPLAY_ID_DEFAULT);
4777 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
4778
4779 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4780 }
4781
4782protected:
4783 std::shared_ptr<FakeApplicationHandle> mApplication;
4784 sp<FakeWindowHandle> mNoInputWindow;
4785 sp<FakeWindowHandle> mBottomWindow;
4786};
4787
4788TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
4789 PointF touchedPoint = {10, 10};
4790
4791 NotifyMotionArgs motionArgs =
4792 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4793 ADISPLAY_ID_DEFAULT, {touchedPoint});
4794 mDispatcher->notifyMotion(&motionArgs);
4795
4796 mNoInputWindow->assertNoEvents();
4797 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
4798 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
4799 // and therefore should prevent mBottomWindow from receiving touches
4800 mBottomWindow->assertNoEvents();
4801}
4802
4803/**
4804 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
4805 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
4806 */
4807TEST_F(InputDispatcherMultiWindowOcclusionTests,
4808 NoInputChannelFeature_DropsTouchesWithValidChannel) {
4809 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4810 "Window with input channel and NO_INPUT_CHANNEL",
4811 ADISPLAY_ID_DEFAULT);
4812
chaviw3277faf2021-05-19 16:45:23 -05004813 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004814 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4815 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4816
4817 PointF touchedPoint = {10, 10};
4818
4819 NotifyMotionArgs motionArgs =
4820 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4821 ADISPLAY_ID_DEFAULT, {touchedPoint});
4822 mDispatcher->notifyMotion(&motionArgs);
4823
4824 mNoInputWindow->assertNoEvents();
4825 mBottomWindow->assertNoEvents();
4826}
4827
Vishnu Nair958da932020-08-21 17:12:37 -07004828class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
4829protected:
4830 std::shared_ptr<FakeApplicationHandle> mApp;
4831 sp<FakeWindowHandle> mWindow;
4832 sp<FakeWindowHandle> mMirror;
4833
4834 virtual void SetUp() override {
4835 InputDispatcherTest::SetUp();
4836 mApp = std::make_shared<FakeApplicationHandle>();
4837 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4838 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
4839 mWindow->getToken());
4840 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4841 mWindow->setFocusable(true);
4842 mMirror->setFocusable(true);
4843 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4844 }
4845};
4846
4847TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
4848 // Request focus on a mirrored window
4849 setFocusedWindow(mMirror);
4850
4851 // window gets focused
4852 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4854 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004855 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4856}
4857
4858// A focused & mirrored window remains focused only if the window and its mirror are both
4859// focusable.
4860TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
4861 setFocusedWindow(mMirror);
4862
4863 // window gets focused
4864 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4866 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004867 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4869 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004870 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4871
4872 mMirror->setFocusable(false);
4873 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4874
4875 // window loses focus since one of the windows associated with the token in not focusable
4876 mWindow->consumeFocusEvent(false);
4877
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004878 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4879 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004880 mWindow->assertNoEvents();
4881}
4882
4883// A focused & mirrored window remains focused until the window and its mirror both become
4884// invisible.
4885TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
4886 setFocusedWindow(mMirror);
4887
4888 // window gets focused
4889 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4891 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004892 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4894 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004895 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4896
4897 mMirror->setVisible(false);
4898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4899
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4901 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004902 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4904 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004905 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4906
4907 mWindow->setVisible(false);
4908 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4909
4910 // window loses focus only after all windows associated with the token become invisible.
4911 mWindow->consumeFocusEvent(false);
4912
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004913 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4914 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004915 mWindow->assertNoEvents();
4916}
4917
4918// A focused & mirrored window remains focused until both windows are removed.
4919TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
4920 setFocusedWindow(mMirror);
4921
4922 // window gets focused
4923 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4925 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004926 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4928 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004929 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4930
4931 // single window is removed but the window token remains focused
4932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
4933
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4935 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004936 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4938 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004939 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4940
4941 // Both windows are removed
4942 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4943 mWindow->consumeFocusEvent(false);
4944
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004945 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4946 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004947 mWindow->assertNoEvents();
4948}
4949
4950// Focus request can be pending until one window becomes visible.
4951TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
4952 // Request focus on an invisible mirror.
4953 mWindow->setVisible(false);
4954 mMirror->setVisible(false);
4955 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4956 setFocusedWindow(mMirror);
4957
4958 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07004960 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004961 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07004962
4963 mMirror->setVisible(true);
4964 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4965
4966 // window gets focused
4967 mWindow->consumeFocusEvent(true);
4968 // window gets the pending key event
4969 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4970}
Prabir Pradhan99987712020-11-10 18:43:05 -08004971
4972class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
4973protected:
4974 std::shared_ptr<FakeApplicationHandle> mApp;
4975 sp<FakeWindowHandle> mWindow;
4976 sp<FakeWindowHandle> mSecondWindow;
4977
4978 void SetUp() override {
4979 InputDispatcherTest::SetUp();
4980 mApp = std::make_shared<FakeApplicationHandle>();
4981 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4982 mWindow->setFocusable(true);
4983 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
4984 mSecondWindow->setFocusable(true);
4985
4986 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4987 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
4988
4989 setFocusedWindow(mWindow);
4990 mWindow->consumeFocusEvent(true);
4991 }
4992
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00004993 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
4994 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08004995 mDispatcher->notifyPointerCaptureChanged(&args);
4996 }
4997
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00004998 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
4999 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08005000 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005001 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
5002 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005003 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005004 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08005005 }
5006};
5007
5008TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
5009 // Ensure that capture cannot be obtained for unfocused windows.
5010 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
5011 mFakePolicy->assertSetPointerCaptureNotCalled();
5012 mSecondWindow->assertNoEvents();
5013
5014 // Ensure that capture can be enabled from the focus window.
5015 requestAndVerifyPointerCapture(mWindow, true);
5016
5017 // Ensure that capture cannot be disabled from a window that does not have capture.
5018 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
5019 mFakePolicy->assertSetPointerCaptureNotCalled();
5020
5021 // Ensure that capture can be disabled from the window with capture.
5022 requestAndVerifyPointerCapture(mWindow, false);
5023}
5024
5025TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005026 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005027
5028 setFocusedWindow(mSecondWindow);
5029
5030 // Ensure that the capture disabled event was sent first.
5031 mWindow->consumeCaptureEvent(false);
5032 mWindow->consumeFocusEvent(false);
5033 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005034 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005035
5036 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005037 notifyPointerCaptureChanged({});
5038 notifyPointerCaptureChanged(request);
5039 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08005040 mWindow->assertNoEvents();
5041 mSecondWindow->assertNoEvents();
5042 mFakePolicy->assertSetPointerCaptureNotCalled();
5043}
5044
5045TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005046 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005047
5048 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005049 notifyPointerCaptureChanged({});
5050 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005051
5052 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005053 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005054 mWindow->consumeCaptureEvent(false);
5055 mWindow->assertNoEvents();
5056}
5057
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005058TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
5059 requestAndVerifyPointerCapture(mWindow, true);
5060
5061 // The first window loses focus.
5062 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005063 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005064 mWindow->consumeCaptureEvent(false);
5065
5066 // Request Pointer Capture from the second window before the notification from InputReader
5067 // arrives.
5068 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005069 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005070
5071 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005072 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005073
5074 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005075 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005076
5077 mSecondWindow->consumeFocusEvent(true);
5078 mSecondWindow->consumeCaptureEvent(true);
5079}
5080
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005081TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
5082 // App repeatedly enables and disables capture.
5083 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5084 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5085 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
5086 mFakePolicy->assertSetPointerCaptureCalled(false);
5087 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5088 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5089
5090 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
5091 // first request is now stale, this should do nothing.
5092 notifyPointerCaptureChanged(firstRequest);
5093 mWindow->assertNoEvents();
5094
5095 // InputReader notifies that the second request was enabled.
5096 notifyPointerCaptureChanged(secondRequest);
5097 mWindow->consumeCaptureEvent(true);
5098}
5099
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005100class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
5101protected:
5102 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00005103
5104 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
5105 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
5106
5107 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
5108 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5109
5110 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
5111 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
5112 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5113 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
5114 MAXIMUM_OBSCURING_OPACITY);
5115
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005116 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005117 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005118 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005119
5120 sp<FakeWindowHandle> mTouchWindow;
5121
5122 virtual void SetUp() override {
5123 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005124 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005125 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
5126 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
5127 }
5128
5129 virtual void TearDown() override {
5130 InputDispatcherTest::TearDown();
5131 mTouchWindow.clear();
5132 }
5133
chaviw3277faf2021-05-19 16:45:23 -05005134 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
5135 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005136 sp<FakeWindowHandle> window = getWindow(uid, name);
chaviw3277faf2021-05-19 16:45:23 -05005137 window->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005138 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005139 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005140 return window;
5141 }
5142
5143 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
5144 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
5145 sp<FakeWindowHandle> window =
5146 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
5147 // Generate an arbitrary PID based on the UID
5148 window->setOwnerInfo(1777 + (uid % 10000), uid);
5149 return window;
5150 }
5151
5152 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
5153 NotifyMotionArgs args =
5154 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5155 ADISPLAY_ID_DEFAULT, points);
5156 mDispatcher->notifyMotion(&args);
5157 }
5158};
5159
5160TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005161 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005162 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005163 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005164
5165 touch();
5166
5167 mTouchWindow->assertNoEvents();
5168}
5169
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005170TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00005171 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
5172 const sp<FakeWindowHandle>& w =
5173 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
5174 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5175
5176 touch();
5177
5178 mTouchWindow->assertNoEvents();
5179}
5180
5181TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005182 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
5183 const sp<FakeWindowHandle>& w =
5184 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5185 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5186
5187 touch();
5188
5189 w->assertNoEvents();
5190}
5191
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005192TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005193 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
5194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005195
5196 touch();
5197
5198 mTouchWindow->consumeAnyMotionDown();
5199}
5200
5201TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005202 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005203 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005204 w->setFrame(Rect(0, 0, 50, 50));
5205 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005206
5207 touch({PointF{100, 100}});
5208
5209 mTouchWindow->consumeAnyMotionDown();
5210}
5211
5212TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005213 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005214 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005215 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5216
5217 touch();
5218
5219 mTouchWindow->consumeAnyMotionDown();
5220}
5221
5222TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
5223 const sp<FakeWindowHandle>& w =
5224 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5225 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005226
5227 touch();
5228
5229 mTouchWindow->consumeAnyMotionDown();
5230}
5231
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005232TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
5233 const sp<FakeWindowHandle>& w =
5234 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5235 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5236
5237 touch();
5238
5239 w->assertNoEvents();
5240}
5241
5242/**
5243 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
5244 * inside) while letting them pass-through. Note that even though touch passes through the occluding
5245 * window, the occluding window will still receive ACTION_OUTSIDE event.
5246 */
5247TEST_F(InputDispatcherUntrustedTouchesTest,
5248 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
5249 const sp<FakeWindowHandle>& w =
5250 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05005251 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5253
5254 touch();
5255
5256 w->consumeMotionOutside();
5257}
5258
5259TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
5260 const sp<FakeWindowHandle>& w =
5261 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05005262 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005263 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5264
5265 touch();
5266
5267 InputEvent* event = w->consume();
5268 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
5269 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5270 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getX());
5271 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getY());
5272}
5273
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005274TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005275 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005276 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5277 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005278 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5279
5280 touch();
5281
5282 mTouchWindow->consumeAnyMotionDown();
5283}
5284
5285TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
5286 const sp<FakeWindowHandle>& w =
5287 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5288 MAXIMUM_OBSCURING_OPACITY);
5289 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005290
5291 touch();
5292
5293 mTouchWindow->consumeAnyMotionDown();
5294}
5295
5296TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005297 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005298 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5299 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005300 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5301
5302 touch();
5303
5304 mTouchWindow->assertNoEvents();
5305}
5306
5307TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
5308 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
5309 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005310 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5311 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005312 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005313 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5314 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005315 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5316
5317 touch();
5318
5319 mTouchWindow->assertNoEvents();
5320}
5321
5322TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
5323 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
5324 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005325 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5326 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005327 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005328 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5329 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005330 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5331
5332 touch();
5333
5334 mTouchWindow->consumeAnyMotionDown();
5335}
5336
5337TEST_F(InputDispatcherUntrustedTouchesTest,
5338 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
5339 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005340 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5341 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005342 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005343 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5344 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005345 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5346
5347 touch();
5348
5349 mTouchWindow->consumeAnyMotionDown();
5350}
5351
5352TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
5353 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005354 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5355 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005356 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005357 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5358 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005359 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005360
5361 touch();
5362
5363 mTouchWindow->assertNoEvents();
5364}
5365
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005366TEST_F(InputDispatcherUntrustedTouchesTest,
5367 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
5368 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005369 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5370 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005371 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005372 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5373 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005374 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5375
5376 touch();
5377
5378 mTouchWindow->assertNoEvents();
5379}
5380
5381TEST_F(InputDispatcherUntrustedTouchesTest,
5382 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
5383 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005384 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5385 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005386 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005387 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5388 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005389 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5390
5391 touch();
5392
5393 mTouchWindow->consumeAnyMotionDown();
5394}
5395
5396TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
5397 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005398 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5399 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005400 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5401
5402 touch();
5403
5404 mTouchWindow->consumeAnyMotionDown();
5405}
5406
5407TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
5408 const sp<FakeWindowHandle>& w =
5409 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
5410 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5411
5412 touch();
5413
5414 mTouchWindow->consumeAnyMotionDown();
5415}
5416
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005417TEST_F(InputDispatcherUntrustedTouchesTest,
5418 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
5419 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5420 const sp<FakeWindowHandle>& w =
5421 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
5422 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5423
5424 touch();
5425
5426 mTouchWindow->assertNoEvents();
5427}
5428
5429TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
5430 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5431 const sp<FakeWindowHandle>& w =
5432 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
5433 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5434
5435 touch();
5436
5437 mTouchWindow->consumeAnyMotionDown();
5438}
5439
5440TEST_F(InputDispatcherUntrustedTouchesTest,
5441 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
5442 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
5443 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005444 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5445 OPACITY_ABOVE_THRESHOLD);
5446 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5447
5448 touch();
5449
5450 mTouchWindow->consumeAnyMotionDown();
5451}
5452
5453TEST_F(InputDispatcherUntrustedTouchesTest,
5454 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
5455 const sp<FakeWindowHandle>& w1 =
5456 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5457 OPACITY_BELOW_THRESHOLD);
5458 const sp<FakeWindowHandle>& w2 =
5459 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5460 OPACITY_BELOW_THRESHOLD);
5461 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5462
5463 touch();
5464
5465 mTouchWindow->assertNoEvents();
5466}
5467
5468/**
5469 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
5470 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
5471 * (which alone would result in allowing touches) does not affect the blocking behavior.
5472 */
5473TEST_F(InputDispatcherUntrustedTouchesTest,
5474 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
5475 const sp<FakeWindowHandle>& wB =
5476 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5477 OPACITY_BELOW_THRESHOLD);
5478 const sp<FakeWindowHandle>& wC =
5479 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5480 OPACITY_BELOW_THRESHOLD);
5481 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5482
5483 touch();
5484
5485 mTouchWindow->assertNoEvents();
5486}
5487
5488/**
5489 * This test is testing that a window from a different UID but with same application token doesn't
5490 * block the touch. Apps can share the application token for close UI collaboration for example.
5491 */
5492TEST_F(InputDispatcherUntrustedTouchesTest,
5493 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
5494 const sp<FakeWindowHandle>& w =
5495 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5496 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005497 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5498
5499 touch();
5500
5501 mTouchWindow->consumeAnyMotionDown();
5502}
5503
arthurhungb89ccb02020-12-30 16:19:01 +08005504class InputDispatcherDragTests : public InputDispatcherTest {
5505protected:
5506 std::shared_ptr<FakeApplicationHandle> mApp;
5507 sp<FakeWindowHandle> mWindow;
5508 sp<FakeWindowHandle> mSecondWindow;
5509 sp<FakeWindowHandle> mDragWindow;
5510
5511 void SetUp() override {
5512 InputDispatcherTest::SetUp();
5513 mApp = std::make_shared<FakeApplicationHandle>();
5514 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5515 mWindow->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05005516 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005517
5518 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5519 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
chaviw3277faf2021-05-19 16:45:23 -05005520 mSecondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005521
5522 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5523 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5524 }
5525
5526 // Start performing drag, we will create a drag window and transfer touch to it.
5527 void performDrag() {
5528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5529 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5530 {50, 50}))
5531 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5532
5533 // Window should receive motion event.
5534 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5535
5536 // The drag window covers the entire display
5537 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5538 mDispatcher->setInputWindows(
5539 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5540
5541 // Transfer touch focus to the drag window
5542 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5543 true /* isDragDrop */);
5544 mWindow->consumeMotionCancel();
5545 mDragWindow->consumeMotionDown();
5546 }
arthurhung6d4bed92021-03-17 11:59:33 +08005547
5548 // Start performing drag, we will create a drag window and transfer touch to it.
5549 void performStylusDrag() {
5550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5551 injectMotionEvent(mDispatcher,
5552 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
5553 AINPUT_SOURCE_STYLUS)
5554 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5555 .pointer(PointerBuilder(0,
5556 AMOTION_EVENT_TOOL_TYPE_STYLUS)
5557 .x(50)
5558 .y(50))
5559 .build()));
5560 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5561
5562 // The drag window covers the entire display
5563 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5564 mDispatcher->setInputWindows(
5565 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5566
5567 // Transfer touch focus to the drag window
5568 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5569 true /* isDragDrop */);
5570 mWindow->consumeMotionCancel();
5571 mDragWindow->consumeMotionDown();
5572 }
arthurhungb89ccb02020-12-30 16:19:01 +08005573};
5574
5575TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
5576 performDrag();
5577
5578 // Move on window.
5579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5580 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5581 ADISPLAY_ID_DEFAULT, {50, 50}))
5582 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5583 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5584 mWindow->consumeDragEvent(false, 50, 50);
5585 mSecondWindow->assertNoEvents();
5586
5587 // Move to another window.
5588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5589 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5590 ADISPLAY_ID_DEFAULT, {150, 50}))
5591 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5592 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5593 mWindow->consumeDragEvent(true, 150, 50);
5594 mSecondWindow->consumeDragEvent(false, 50, 50);
5595
5596 // Move back to original window.
5597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5598 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5599 ADISPLAY_ID_DEFAULT, {50, 50}))
5600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5601 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5602 mWindow->consumeDragEvent(false, 50, 50);
5603 mSecondWindow->consumeDragEvent(true, -50, 50);
5604
5605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5606 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
5607 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5608 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5609 mWindow->assertNoEvents();
5610 mSecondWindow->assertNoEvents();
5611}
5612
arthurhungf452d0b2021-01-06 00:19:52 +08005613TEST_F(InputDispatcherDragTests, DragAndDrop) {
5614 performDrag();
5615
5616 // Move on window.
5617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5618 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5619 ADISPLAY_ID_DEFAULT, {50, 50}))
5620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5621 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5622 mWindow->consumeDragEvent(false, 50, 50);
5623 mSecondWindow->assertNoEvents();
5624
5625 // Move to another window.
5626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5627 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5628 ADISPLAY_ID_DEFAULT, {150, 50}))
5629 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5630 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5631 mWindow->consumeDragEvent(true, 150, 50);
5632 mSecondWindow->consumeDragEvent(false, 50, 50);
5633
5634 // drop to another window.
5635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5636 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5637 {150, 50}))
5638 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5639 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5640 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5641 mWindow->assertNoEvents();
5642 mSecondWindow->assertNoEvents();
5643}
5644
arthurhung6d4bed92021-03-17 11:59:33 +08005645TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
5646 performStylusDrag();
5647
5648 // Move on window and keep button pressed.
5649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5650 injectMotionEvent(mDispatcher,
5651 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5652 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5653 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5654 .x(50)
5655 .y(50))
5656 .build()))
5657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5658 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5659 mWindow->consumeDragEvent(false, 50, 50);
5660 mSecondWindow->assertNoEvents();
5661
5662 // Move to another window and release button, expect to drop item.
5663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5664 injectMotionEvent(mDispatcher,
5665 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5666 .buttonState(0)
5667 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5668 .x(150)
5669 .y(50))
5670 .build()))
5671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5672 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5673 mWindow->assertNoEvents();
5674 mSecondWindow->assertNoEvents();
5675 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5676
5677 // nothing to the window.
5678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5679 injectMotionEvent(mDispatcher,
5680 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
5681 .buttonState(0)
5682 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5683 .x(150)
5684 .y(50))
5685 .build()))
5686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5687 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5688 mWindow->assertNoEvents();
5689 mSecondWindow->assertNoEvents();
5690}
5691
Arthur Hung6d0571e2021-04-09 20:18:16 +08005692TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
5693 performDrag();
5694
5695 // Set second window invisible.
5696 mSecondWindow->setVisible(false);
5697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5698
5699 // Move on window.
5700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5701 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5702 ADISPLAY_ID_DEFAULT, {50, 50}))
5703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5704 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5705 mWindow->consumeDragEvent(false, 50, 50);
5706 mSecondWindow->assertNoEvents();
5707
5708 // Move to another window.
5709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5710 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5711 ADISPLAY_ID_DEFAULT, {150, 50}))
5712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5713 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5714 mWindow->consumeDragEvent(true, 150, 50);
5715 mSecondWindow->assertNoEvents();
5716
5717 // drop to another window.
5718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5719 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5720 {150, 50}))
5721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5722 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5723 mFakePolicy->assertDropTargetEquals(nullptr);
5724 mWindow->assertNoEvents();
5725 mSecondWindow->assertNoEvents();
5726}
5727
Vishnu Nair062a8672021-09-03 16:07:44 -07005728class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
5729
5730TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
5731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5732 sp<FakeWindowHandle> window =
5733 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5734 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT);
5735 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5736 window->setFocusable(true);
5737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5738 setFocusedWindow(window);
5739 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5740
5741 // With the flag set, window should not get any input
5742 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5743 mDispatcher->notifyKey(&keyArgs);
5744 window->assertNoEvents();
5745
5746 NotifyMotionArgs motionArgs =
5747 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5748 ADISPLAY_ID_DEFAULT);
5749 mDispatcher->notifyMotion(&motionArgs);
5750 window->assertNoEvents();
5751
5752 // With the flag cleared, the window should get input
5753 window->setInputFeatures({});
5754 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5755
5756 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5757 mDispatcher->notifyKey(&keyArgs);
5758 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5759
5760 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5761 ADISPLAY_ID_DEFAULT);
5762 mDispatcher->notifyMotion(&motionArgs);
5763 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5764 window->assertNoEvents();
5765}
5766
5767TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
5768 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
5769 std::make_shared<FakeApplicationHandle>();
5770 sp<FakeWindowHandle> obscuringWindow =
5771 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
5772 ADISPLAY_ID_DEFAULT);
5773 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
5774 obscuringWindow->setOwnerInfo(111, 111);
5775 obscuringWindow->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
5776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5777 sp<FakeWindowHandle> window =
5778 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5779 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
5780 window->setOwnerInfo(222, 222);
5781 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5782 window->setFocusable(true);
5783 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5784 setFocusedWindow(window);
5785 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5786
5787 // With the flag set, window should not get any input
5788 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5789 mDispatcher->notifyKey(&keyArgs);
5790 window->assertNoEvents();
5791
5792 NotifyMotionArgs motionArgs =
5793 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5794 ADISPLAY_ID_DEFAULT);
5795 mDispatcher->notifyMotion(&motionArgs);
5796 window->assertNoEvents();
5797
5798 // With the flag cleared, the window should get input
5799 window->setInputFeatures({});
5800 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5801
5802 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5803 mDispatcher->notifyKey(&keyArgs);
5804 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5805
5806 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5807 ADISPLAY_ID_DEFAULT);
5808 mDispatcher->notifyMotion(&motionArgs);
5809 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5810 window->assertNoEvents();
5811}
5812
5813TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
5814 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
5815 std::make_shared<FakeApplicationHandle>();
5816 sp<FakeWindowHandle> obscuringWindow =
5817 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
5818 ADISPLAY_ID_DEFAULT);
5819 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
5820 obscuringWindow->setOwnerInfo(111, 111);
5821 obscuringWindow->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
5822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5823 sp<FakeWindowHandle> window =
5824 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
5825 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
5826 window->setOwnerInfo(222, 222);
5827 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5828 window->setFocusable(true);
5829 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
5830 setFocusedWindow(window);
5831 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
5832
5833 // With the flag set, window should not get any input
5834 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
5835 mDispatcher->notifyKey(&keyArgs);
5836 window->assertNoEvents();
5837
5838 NotifyMotionArgs motionArgs =
5839 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5840 ADISPLAY_ID_DEFAULT);
5841 mDispatcher->notifyMotion(&motionArgs);
5842 window->assertNoEvents();
5843
5844 // When the window is no longer obscured because it went on top, it should get input
5845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
5846
5847 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
5848 mDispatcher->notifyKey(&keyArgs);
5849 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
5850
5851 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5852 ADISPLAY_ID_DEFAULT);
5853 mDispatcher->notifyMotion(&motionArgs);
5854 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5855 window->assertNoEvents();
5856}
5857
Garfield Tane84e6f92019-08-29 17:28:41 -07005858} // namespace android::inputdispatcher