blob: e223372fe1f54f664e1b800b08ce6547f511bfcc [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,
Evan Rosky09576692021-07-01 12:22:09 -0700545 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
546 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700547 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800548 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700549 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800550 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551 << "Should reject motion events with 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,
Evan Rosky09576692021-07-01 12:22:09 -0700559 ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
560 ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500561 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800562 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700563 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800564 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800565 << "Should reject motion events with pointer down index too large.";
566
Garfield Tanfbe732e2020-01-24 11:26:14 -0800567 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700568 AMOTION_EVENT_ACTION_POINTER_DOWN |
569 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700570 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
571 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700572 ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
573 ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500574 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800575 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700576 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800577 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800578 << "Should reject motion events with pointer down index too small.";
579
580 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800581 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700582 AMOTION_EVENT_ACTION_POINTER_UP |
583 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700584 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
585 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700586 ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
587 ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500588 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800589 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700590 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800591 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800592 << "Should reject motion events with pointer up index too large.";
593
Garfield Tanfbe732e2020-01-24 11:26:14 -0800594 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700595 AMOTION_EVENT_ACTION_POINTER_UP |
596 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700597 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
598 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700599 ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
600 ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500601 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800602 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700603 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800604 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800605 << "Should reject motion events with pointer up index too small.";
606
607 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800608 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
609 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700610 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700611 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
612 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700613 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800614 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700615 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800616 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617 << "Should reject motion events with 0 pointers.";
618
Garfield Tanfbe732e2020-01-24 11:26:14 -0800619 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
620 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700621 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700622 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
623 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700624 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800625 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700626 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800627 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800628 << "Should reject motion events with more than MAX_POINTERS pointers.";
629
630 // Rejects motion events with invalid pointer ids.
631 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800632 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
633 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700634 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700635 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
636 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700637 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800638 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700639 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800640 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800641 << "Should reject motion events with pointer ids less than 0.";
642
643 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800644 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
645 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700646 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700647 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
648 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700649 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800650 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700651 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800652 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
654
655 // Rejects motion events with duplicate pointer ids.
656 pointerProperties[0].id = 1;
657 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800658 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
659 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700660 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700661 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
662 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700663 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800664 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700665 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800666 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800667 << "Should reject motion events with duplicate pointer ids.";
668}
669
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800670/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
671
672TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
673 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800674 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800675 mDispatcher->notifyConfigurationChanged(&args);
676 ASSERT_TRUE(mDispatcher->waitForIdle());
677
678 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
679}
680
681TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800682 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
683 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800684 mDispatcher->notifySwitch(&args);
685
686 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
687 args.policyFlags |= POLICY_FLAG_TRUSTED;
688 mFakePolicy->assertNotifySwitchWasCalled(args);
689}
690
Arthur Hungb92218b2018-08-14 12:00:21 +0800691// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700692static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700693// Default input dispatching timeout if there is no focused application or paused window
694// from which to determine an appropriate dispatching timeout.
695static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
696 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
697 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800698
699class FakeApplicationHandle : public InputApplicationHandle {
700public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700701 FakeApplicationHandle() {
702 mInfo.name = "Fake Application";
703 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500704 mInfo.dispatchingTimeoutMillis =
705 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700706 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800707 virtual ~FakeApplicationHandle() {}
708
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000709 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700710
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500711 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
712 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700713 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800714};
715
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800716class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800717public:
Garfield Tan15601662020-09-22 15:32:38 -0700718 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800719 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700720 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800721 }
722
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800723 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700724 InputEvent* event;
725 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
726 if (!consumeSeq) {
727 return nullptr;
728 }
729 finishEvent(*consumeSeq);
730 return event;
731 }
732
733 /**
734 * Receive an event without acknowledging it.
735 * Return the sequence number that could later be used to send finished signal.
736 */
737 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800738 uint32_t consumeSeq;
739 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800740
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800741 std::chrono::time_point start = std::chrono::steady_clock::now();
742 status_t status = WOULD_BLOCK;
743 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800744 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800745 &event);
746 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
747 if (elapsed > 100ms) {
748 break;
749 }
750 }
751
752 if (status == WOULD_BLOCK) {
753 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700754 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800755 }
756
757 if (status != OK) {
758 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700759 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800760 }
761 if (event == nullptr) {
762 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700763 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800764 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700765 if (outEvent != nullptr) {
766 *outEvent = event;
767 }
768 return consumeSeq;
769 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800770
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700771 /**
772 * To be used together with "receiveEvent" to complete the consumption of an event.
773 */
774 void finishEvent(uint32_t consumeSeq) {
775 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
776 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800777 }
778
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000779 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
780 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
781 ASSERT_EQ(OK, status);
782 }
783
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000784 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
785 std::optional<int32_t> expectedDisplayId,
786 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800787 InputEvent* event = consume();
788
789 ASSERT_NE(nullptr, event) << mName.c_str()
790 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800791 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700792 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800793 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800794
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000795 if (expectedDisplayId.has_value()) {
796 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
797 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800798
Tiger Huang8664f8c2018-10-11 19:14:35 +0800799 switch (expectedEventType) {
800 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800801 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
802 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000803 if (expectedFlags.has_value()) {
804 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
805 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800806 break;
807 }
808 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800809 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000810 assertMotionAction(expectedAction, motionEvent.getAction());
811
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000812 if (expectedFlags.has_value()) {
813 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
814 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800815 break;
816 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100817 case AINPUT_EVENT_TYPE_FOCUS: {
818 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
819 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800820 case AINPUT_EVENT_TYPE_CAPTURE: {
821 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
822 }
arthurhungb89ccb02020-12-30 16:19:01 +0800823 case AINPUT_EVENT_TYPE_DRAG: {
824 FAIL() << "Use 'consumeDragEvent' for DRAG events";
825 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800826 default: {
827 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
828 }
829 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800830 }
831
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100832 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
833 InputEvent* event = consume();
834 ASSERT_NE(nullptr, event) << mName.c_str()
835 << ": consumer should have returned non-NULL event.";
836 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
837 << "Got " << inputEventTypeToString(event->getType())
838 << " event instead of FOCUS event";
839
840 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
841 << mName.c_str() << ": event displayId should always be NONE.";
842
843 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
844 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
845 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
846 }
847
Prabir Pradhan99987712020-11-10 18:43:05 -0800848 void consumeCaptureEvent(bool hasCapture) {
849 const InputEvent* event = consume();
850 ASSERT_NE(nullptr, event) << mName.c_str()
851 << ": consumer should have returned non-NULL event.";
852 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
853 << "Got " << inputEventTypeToString(event->getType())
854 << " event instead of CAPTURE event";
855
856 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
857 << mName.c_str() << ": event displayId should always be NONE.";
858
859 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
860 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
861 }
862
arthurhungb89ccb02020-12-30 16:19:01 +0800863 void consumeDragEvent(bool isExiting, float x, float y) {
864 const InputEvent* event = consume();
865 ASSERT_NE(nullptr, event) << mName.c_str()
866 << ": consumer should have returned non-NULL event.";
867 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
868 << "Got " << inputEventTypeToString(event->getType())
869 << " event instead of DRAG event";
870
871 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
872 << mName.c_str() << ": event displayId should always be NONE.";
873
874 const auto& dragEvent = static_cast<const DragEvent&>(*event);
875 EXPECT_EQ(isExiting, dragEvent.isExiting());
876 EXPECT_EQ(x, dragEvent.getX());
877 EXPECT_EQ(y, dragEvent.getY());
878 }
879
chaviwd1c23182019-12-20 18:44:56 -0800880 void assertNoEvents() {
881 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700882 if (event == nullptr) {
883 return;
884 }
885 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
886 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
887 ADD_FAILURE() << "Received key event "
888 << KeyEvent::actionToString(keyEvent.getAction());
889 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
890 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
891 ADD_FAILURE() << "Received motion event "
892 << MotionEvent::actionToString(motionEvent.getAction());
893 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
894 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
895 ADD_FAILURE() << "Received focus event, hasFocus = "
896 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800897 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
898 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
899 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
900 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700901 }
902 FAIL() << mName.c_str()
903 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800904 }
905
906 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
907
908protected:
909 std::unique_ptr<InputConsumer> mConsumer;
910 PreallocatedInputEventFactory mEventFactory;
911
912 std::string mName;
913};
914
chaviw3277faf2021-05-19 16:45:23 -0500915class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -0800916public:
917 static const int32_t WIDTH = 600;
918 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800919
Chris Yea209fde2020-07-22 13:54:51 -0700920 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800921 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500922 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800923 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500924 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700925 base::Result<std::unique_ptr<InputChannel>> channel =
926 dispatcher->createInputChannel(name);
927 token = (*channel)->getConnectionToken();
928 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800929 }
930
931 inputApplicationHandle->updateInfo();
932 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
933
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500934 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700935 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800936 mInfo.name = name;
chaviw3277faf2021-05-19 16:45:23 -0500937 mInfo.type = WindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500938 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000939 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -0800940 mInfo.frameLeft = 0;
941 mInfo.frameTop = 0;
942 mInfo.frameRight = WIDTH;
943 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700944 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800945 mInfo.globalScaleFactor = 1.0;
946 mInfo.touchableRegion.clear();
947 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
948 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700949 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800950 mInfo.hasWallpaper = false;
951 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800952 mInfo.ownerPid = INJECTOR_PID;
953 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800954 mInfo.displayId = displayId;
955 }
956
Arthur Hungabbb9d82021-09-01 14:52:30 +0000957 sp<FakeWindowHandle> clone(
958 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
959 const sp<InputDispatcher>& dispatcher, int32_t displayId) {
960 sp<FakeWindowHandle> handle =
961 new FakeWindowHandle(inputApplicationHandle, dispatcher, mInfo.name + "(Mirror)",
962 displayId, mInfo.token);
963 return handle;
964 }
965
Vishnu Nair47074b82020-08-14 11:54:47 -0700966 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800967
Vishnu Nair958da932020-08-21 17:12:37 -0700968 void setVisible(bool visible) { mInfo.visible = visible; }
969
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700970 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500971 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700972 }
973
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700974 void setPaused(bool paused) { mInfo.paused = paused; }
975
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000976 void setAlpha(float alpha) { mInfo.alpha = alpha; }
977
chaviw3277faf2021-05-19 16:45:23 -0500978 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000979
Bernardo Rufino7393d172021-02-26 13:56:11 +0000980 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
981
chaviwd1c23182019-12-20 18:44:56 -0800982 void setFrame(const Rect& frame) {
983 mInfo.frameLeft = frame.left;
984 mInfo.frameTop = frame.top;
985 mInfo.frameRight = frame.right;
986 mInfo.frameBottom = frame.bottom;
arthurhungb89ccb02020-12-30 16:19:01 +0800987 mInfo.transform.set(-frame.left, -frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800988 mInfo.touchableRegion.clear();
989 mInfo.addTouchableRegion(frame);
990 }
991
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000992 void setType(WindowInfo::Type type) { mInfo.type = type; }
993
994 void setHasWallpaper(bool hasWallpaper) { mInfo.hasWallpaper = hasWallpaper; }
995
chaviw3277faf2021-05-19 16:45:23 -0500996 void addFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags |= flags; }
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +0000997
chaviw3277faf2021-05-19 16:45:23 -0500998 void setFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800999
chaviw3277faf2021-05-19 16:45:23 -05001000 void setInputFeatures(WindowInfo::Feature features) { mInfo.inputFeatures = features; }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001001
chaviw9eaa22c2020-07-01 16:21:27 -07001002 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1003 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1004 }
1005
1006 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001007
yunho.shinf4a80b82020-11-16 21:13:57 +09001008 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1009
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001010 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1011 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1012 expectedFlags);
1013 }
1014
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001015 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1016 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1017 }
1018
Svet Ganov5d3bc372020-01-26 23:11:07 -08001019 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001020 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001021 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
1022 expectedFlags);
1023 }
1024
1025 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001026 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001027 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
1028 expectedFlags);
1029 }
1030
1031 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001032 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001033 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1034 }
1035
1036 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1037 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001038 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1039 expectedFlags);
1040 }
1041
Svet Ganov5d3bc372020-01-26 23:11:07 -08001042 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001043 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1044 int32_t expectedFlags = 0) {
1045 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1046 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001047 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1048 }
1049
1050 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001051 int32_t expectedFlags = 0) {
1052 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1053 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001054 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1055 }
1056
1057 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001058 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001059 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1060 expectedFlags);
1061 }
1062
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001063 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1064 int32_t expectedFlags = 0) {
1065 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1066 expectedFlags);
1067 }
1068
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001069 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1070 ASSERT_NE(mInputReceiver, nullptr)
1071 << "Cannot consume events from a window with no receiver";
1072 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1073 }
1074
Prabir Pradhan99987712020-11-10 18:43:05 -08001075 void consumeCaptureEvent(bool hasCapture) {
1076 ASSERT_NE(mInputReceiver, nullptr)
1077 << "Cannot consume events from a window with no receiver";
1078 mInputReceiver->consumeCaptureEvent(hasCapture);
1079 }
1080
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001081 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1082 std::optional<int32_t> expectedDisplayId,
1083 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001084 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1085 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1086 expectedFlags);
1087 }
1088
arthurhungb89ccb02020-12-30 16:19:01 +08001089 void consumeDragEvent(bool isExiting, float x, float y) {
1090 mInputReceiver->consumeDragEvent(isExiting, x, y);
1091 }
1092
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001093 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001094 if (mInputReceiver == nullptr) {
1095 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1096 return std::nullopt;
1097 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001098 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001099 }
1100
1101 void finishEvent(uint32_t sequenceNum) {
1102 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1103 mInputReceiver->finishEvent(sequenceNum);
1104 }
1105
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001106 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1107 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1108 mInputReceiver->sendTimeline(inputEventId, timeline);
1109 }
1110
chaviwaf87b3e2019-10-01 16:59:28 -07001111 InputEvent* consume() {
1112 if (mInputReceiver == nullptr) {
1113 return nullptr;
1114 }
1115 return mInputReceiver->consume();
1116 }
1117
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001118 MotionEvent* consumeMotion() {
1119 InputEvent* event = consume();
1120 if (event == nullptr) {
1121 ADD_FAILURE() << "Consume failed : no event";
1122 return nullptr;
1123 }
1124 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1125 ADD_FAILURE() << "Instead of motion event, got "
1126 << inputEventTypeToString(event->getType());
1127 return nullptr;
1128 }
1129 return static_cast<MotionEvent*>(event);
1130 }
1131
Arthur Hungb92218b2018-08-14 12:00:21 +08001132 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001133 if (mInputReceiver == nullptr &&
chaviw3277faf2021-05-19 16:45:23 -05001134 mInfo.inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001135 return; // Can't receive events if the window does not have input channel
1136 }
1137 ASSERT_NE(nullptr, mInputReceiver)
1138 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001139 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001140 }
1141
chaviwaf87b3e2019-10-01 16:59:28 -07001142 sp<IBinder> getToken() { return mInfo.token; }
1143
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001144 const std::string& getName() { return mName; }
1145
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001146 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1147 mInfo.ownerPid = ownerPid;
1148 mInfo.ownerUid = ownerUid;
1149 }
1150
chaviwd1c23182019-12-20 18:44:56 -08001151private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001152 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001153 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001154 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001155};
1156
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001157std::atomic<int32_t> FakeWindowHandle::sId{1};
1158
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001159static InputEventInjectionResult injectKey(
1160 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
1161 int32_t displayId = ADISPLAY_ID_NONE,
1162 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001163 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1164 bool allowKeyRepeat = true) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001165 KeyEvent event;
1166 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1167
1168 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001169 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001170 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1171 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001172
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001173 int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
1174 if (!allowKeyRepeat) {
1175 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1176 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001177 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001178 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001179 injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001180}
1181
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001182static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
1183 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001184 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1185}
1186
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001187// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1188// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1189// has to be woken up to process the repeating key.
1190static InputEventInjectionResult injectKeyDownNoRepeat(const sp<InputDispatcher>& dispatcher,
1191 int32_t displayId = ADISPLAY_ID_NONE) {
1192 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1193 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1194 /* allowKeyRepeat */ false);
1195}
1196
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001197static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
1198 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001199 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1200}
1201
Garfield Tandf26e862020-07-01 20:18:19 -07001202class PointerBuilder {
1203public:
1204 PointerBuilder(int32_t id, int32_t toolType) {
1205 mProperties.clear();
1206 mProperties.id = id;
1207 mProperties.toolType = toolType;
1208 mCoords.clear();
1209 }
1210
1211 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1212
1213 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1214
1215 PointerBuilder& axis(int32_t axis, float value) {
1216 mCoords.setAxisValue(axis, value);
1217 return *this;
1218 }
1219
1220 PointerProperties buildProperties() const { return mProperties; }
1221
1222 PointerCoords buildCoords() const { return mCoords; }
1223
1224private:
1225 PointerProperties mProperties;
1226 PointerCoords mCoords;
1227};
1228
1229class MotionEventBuilder {
1230public:
1231 MotionEventBuilder(int32_t action, int32_t source) {
1232 mAction = action;
1233 mSource = source;
1234 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1235 }
1236
1237 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1238 mEventTime = eventTime;
1239 return *this;
1240 }
1241
1242 MotionEventBuilder& displayId(int32_t displayId) {
1243 mDisplayId = displayId;
1244 return *this;
1245 }
1246
1247 MotionEventBuilder& actionButton(int32_t actionButton) {
1248 mActionButton = actionButton;
1249 return *this;
1250 }
1251
arthurhung6d4bed92021-03-17 11:59:33 +08001252 MotionEventBuilder& buttonState(int32_t buttonState) {
1253 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001254 return *this;
1255 }
1256
1257 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1258 mRawXCursorPosition = rawXCursorPosition;
1259 return *this;
1260 }
1261
1262 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1263 mRawYCursorPosition = rawYCursorPosition;
1264 return *this;
1265 }
1266
1267 MotionEventBuilder& pointer(PointerBuilder pointer) {
1268 mPointers.push_back(pointer);
1269 return *this;
1270 }
1271
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001272 MotionEventBuilder& addFlag(uint32_t flags) {
1273 mFlags |= flags;
1274 return *this;
1275 }
1276
Garfield Tandf26e862020-07-01 20:18:19 -07001277 MotionEvent build() {
1278 std::vector<PointerProperties> pointerProperties;
1279 std::vector<PointerCoords> pointerCoords;
1280 for (const PointerBuilder& pointer : mPointers) {
1281 pointerProperties.push_back(pointer.buildProperties());
1282 pointerCoords.push_back(pointer.buildCoords());
1283 }
1284
1285 // Set mouse cursor position for the most common cases to avoid boilerplate.
1286 if (mSource == AINPUT_SOURCE_MOUSE &&
1287 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1288 mPointers.size() == 1) {
1289 mRawXCursorPosition = pointerCoords[0].getX();
1290 mRawYCursorPosition = pointerCoords[0].getY();
1291 }
1292
1293 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001294 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001295 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001296 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001297 mButtonState, MotionClassification::NONE, identityTransform,
1298 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Evan Rosky09576692021-07-01 12:22:09 -07001299 mRawYCursorPosition, mDisplayOrientation, mDisplayWidth, mDisplayHeight,
1300 mEventTime, mEventTime, mPointers.size(), pointerProperties.data(),
1301 pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001302
1303 return event;
1304 }
1305
1306private:
1307 int32_t mAction;
1308 int32_t mSource;
1309 nsecs_t mEventTime;
1310 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1311 int32_t mActionButton{0};
1312 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001313 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001314 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1315 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
Evan Rosky09576692021-07-01 12:22:09 -07001316 uint32_t mDisplayOrientation{ui::Transform::ROT_0};
chaviw3277faf2021-05-19 16:45:23 -05001317 int32_t mDisplayWidth{INVALID_DISPLAY_SIZE};
1318 int32_t mDisplayHeight{INVALID_DISPLAY_SIZE};
Garfield Tandf26e862020-07-01 20:18:19 -07001319
1320 std::vector<PointerBuilder> mPointers;
1321};
1322
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001323static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001324 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1325 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001326 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001327 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1328 injectionTimeout,
1329 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1330}
1331
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001332static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001333 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1334 const PointF& position,
1335 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001336 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1337 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001338 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001339 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001340 MotionEvent event = MotionEventBuilder(action, source)
1341 .displayId(displayId)
1342 .eventTime(eventTime)
1343 .rawXCursorPosition(cursorPosition.x)
1344 .rawYCursorPosition(cursorPosition.y)
1345 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1346 .x(position.x)
1347 .y(position.y))
1348 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001349
1350 // Inject event until dispatch out.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001351 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode);
Arthur Hungb92218b2018-08-14 12:00:21 +08001352}
1353
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001354static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1355 int32_t source, int32_t displayId,
1356 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001357 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001358}
1359
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001360static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1361 int32_t source, int32_t displayId,
1362 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001363 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001364}
1365
Jackal Guof9696682018-10-05 12:23:23 +08001366static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1367 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1368 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001369 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1370 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1371 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001372
1373 return args;
1374}
1375
chaviwd1c23182019-12-20 18:44:56 -08001376static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1377 const std::vector<PointF>& points) {
1378 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001379 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1380 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1381 }
1382
chaviwd1c23182019-12-20 18:44:56 -08001383 PointerProperties pointerProperties[pointerCount];
1384 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001385
chaviwd1c23182019-12-20 18:44:56 -08001386 for (size_t i = 0; i < pointerCount; i++) {
1387 pointerProperties[i].clear();
1388 pointerProperties[i].id = i;
1389 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001390
chaviwd1c23182019-12-20 18:44:56 -08001391 pointerCoords[i].clear();
1392 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1393 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1394 }
Jackal Guof9696682018-10-05 12:23:23 +08001395
1396 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1397 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001398 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001399 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1400 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001401 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1402 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001403 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1404 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001405
1406 return args;
1407}
1408
chaviwd1c23182019-12-20 18:44:56 -08001409static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1410 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1411}
1412
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001413static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1414 const PointerCaptureRequest& request) {
1415 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001416}
1417
Arthur Hungb92218b2018-08-14 12:00:21 +08001418TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001419 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001420 sp<FakeWindowHandle> window =
1421 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001422
Arthur Hung72d8dc32020-03-28 00:48:39 +00001423 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1425 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001427
1428 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001429 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001430}
1431
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001432/**
1433 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1434 * To ensure that window receives only events that were directly inside of it, add
1435 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1436 * when finding touched windows.
1437 * This test serves as a sanity check for the next test, where setInputWindows is
1438 * called twice.
1439 */
1440TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001441 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001442 sp<FakeWindowHandle> window =
1443 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1444 window->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05001445 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001446
1447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001449 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1450 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001452
1453 // Window should receive motion event.
1454 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1455}
1456
1457/**
1458 * Calling setInputWindows twice, with the same info, should not cause any issues.
1459 * To ensure that window receives only events that were directly inside of it, add
1460 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1461 * when finding touched windows.
1462 */
1463TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001465 sp<FakeWindowHandle> window =
1466 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1467 window->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05001468 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001469
1470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1471 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001473 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1474 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001475 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001476
1477 // Window should receive motion event.
1478 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1479}
1480
Arthur Hungb92218b2018-08-14 12:00:21 +08001481// The foreground window should receive the first touch down event.
1482TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001483 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001484 sp<FakeWindowHandle> windowTop =
1485 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1486 sp<FakeWindowHandle> windowSecond =
1487 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001488
Arthur Hung72d8dc32020-03-28 00:48:39 +00001489 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1491 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1492 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001493
1494 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001495 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001496 windowSecond->assertNoEvents();
1497}
1498
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001499/**
1500 * Two windows: A top window, and a wallpaper behind the window.
1501 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1502 * gets ACTION_CANCEL.
1503 * 1. foregroundWindow <-- has wallpaper (hasWallpaper=true)
1504 * 2. wallpaperWindow <-- is wallpaper (type=InputWindowInfo::Type::WALLPAPER)
1505 */
1506TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1507 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1508 sp<FakeWindowHandle> foregroundWindow =
1509 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1510 foregroundWindow->setHasWallpaper(true);
1511 sp<FakeWindowHandle> wallpaperWindow =
1512 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1513 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1514 constexpr int expectedWallpaperFlags =
1515 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1516
1517 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1519 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1520 {100, 200}))
1521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1522
1523 // Both foreground window and its wallpaper should receive the touch down
1524 foregroundWindow->consumeMotionDown();
1525 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1526
1527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1528 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1529 ADISPLAY_ID_DEFAULT, {110, 200}))
1530 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1531
1532 foregroundWindow->consumeMotionMove();
1533 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1534
1535 // Now the foreground window goes away, but the wallpaper stays
1536 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1537 foregroundWindow->consumeMotionCancel();
1538 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1539 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1540}
1541
1542/**
1543 * A single window that receives touch (on top), and a wallpaper window underneath it.
1544 * The top window gets a multitouch gesture.
1545 * Ensure that wallpaper gets the same gesture.
1546 */
1547TEST_F(InputDispatcherTest, WallpaperWindow_ReceivesMultiTouch) {
1548 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1549 sp<FakeWindowHandle> window =
1550 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1551 window->setHasWallpaper(true);
1552
1553 sp<FakeWindowHandle> wallpaperWindow =
1554 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1555 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1556 constexpr int expectedWallpaperFlags =
1557 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1558
1559 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1560
1561 // Touch down on top window
1562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1563 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1564 {100, 100}))
1565 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1566
1567 // Both top window and its wallpaper should receive the touch down
1568 window->consumeMotionDown();
1569 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1570
1571 // Second finger down on the top window
1572 const MotionEvent secondFingerDownEvent =
1573 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1574 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1575 AINPUT_SOURCE_TOUCHSCREEN)
1576 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1577 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1578 .x(100)
1579 .y(100))
1580 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1581 .x(150)
1582 .y(150))
1583 .build();
1584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1585 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1586 InputEventInjectionSync::WAIT_FOR_RESULT))
1587 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1588
1589 window->consumeMotionPointerDown(1 /* pointerIndex */);
1590 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1591 expectedWallpaperFlags);
1592 window->assertNoEvents();
1593 wallpaperWindow->assertNoEvents();
1594}
1595
1596/**
1597 * Two windows: a window on the left and window on the right.
1598 * A third window, wallpaper, is behind both windows, and spans both top windows.
1599 * The first touch down goes to the left window. A second pointer touches down on the right window.
1600 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1601 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1602 * ACTION_POINTER_DOWN(1).
1603 */
1604TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1606 sp<FakeWindowHandle> leftWindow =
1607 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1608 leftWindow->setFrame(Rect(0, 0, 200, 200));
1609 leftWindow->setFlags(WindowInfo::Flag::SPLIT_TOUCH | WindowInfo::Flag::NOT_TOUCH_MODAL);
1610 leftWindow->setHasWallpaper(true);
1611
1612 sp<FakeWindowHandle> rightWindow =
1613 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1614 rightWindow->setFrame(Rect(200, 0, 400, 200));
1615 rightWindow->setFlags(WindowInfo::Flag::SPLIT_TOUCH | WindowInfo::Flag::NOT_TOUCH_MODAL);
1616 rightWindow->setHasWallpaper(true);
1617
1618 sp<FakeWindowHandle> wallpaperWindow =
1619 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1620 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
1621 wallpaperWindow->setType(WindowInfo::Type::WALLPAPER);
1622 constexpr int expectedWallpaperFlags =
1623 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1624
1625 mDispatcher->setInputWindows(
1626 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1627
1628 // Touch down on left window
1629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1630 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1631 {100, 100}))
1632 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1633
1634 // Both foreground window and its wallpaper should receive the touch down
1635 leftWindow->consumeMotionDown();
1636 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1637
1638 // Second finger down on the right window
1639 const MotionEvent secondFingerDownEvent =
1640 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1641 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1642 AINPUT_SOURCE_TOUCHSCREEN)
1643 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1644 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1645 .x(100)
1646 .y(100))
1647 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1648 .x(300)
1649 .y(100))
1650 .build();
1651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1652 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1653 InputEventInjectionSync::WAIT_FOR_RESULT))
1654 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1655
1656 leftWindow->consumeMotionMove();
1657 // Since the touch is split, right window gets ACTION_DOWN
1658 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1659 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1660 expectedWallpaperFlags);
1661
1662 // Now, leftWindow, which received the first finger, disappears.
1663 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1664 leftWindow->consumeMotionCancel();
1665 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1666 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1667
1668 // The pointer that's still down on the right window moves, and goes to the right window only.
1669 // As far as the dispatcher's concerned though, both pointers are still present.
1670 const MotionEvent secondFingerMoveEvent =
1671 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1672 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1673 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1674 .x(100)
1675 .y(100))
1676 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1677 .x(310)
1678 .y(110))
1679 .build();
1680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1681 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1682 InputEventInjectionSync::WAIT_FOR_RESULT));
1683 rightWindow->consumeMotionMove();
1684
1685 leftWindow->assertNoEvents();
1686 rightWindow->assertNoEvents();
1687 wallpaperWindow->assertNoEvents();
1688}
1689
Garfield Tandf26e862020-07-01 20:18:19 -07001690TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001692 sp<FakeWindowHandle> windowLeft =
1693 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1694 windowLeft->setFrame(Rect(0, 0, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001695 windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001696 sp<FakeWindowHandle> windowRight =
1697 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1698 windowRight->setFrame(Rect(600, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001699 windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001700
1701 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1702
1703 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1704
1705 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001707 injectMotionEvent(mDispatcher,
1708 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1709 AINPUT_SOURCE_MOUSE)
1710 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1711 .x(900)
1712 .y(400))
1713 .build()));
1714 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1715 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1716 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1717 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1718
1719 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001721 injectMotionEvent(mDispatcher,
1722 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1723 AINPUT_SOURCE_MOUSE)
1724 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1725 .x(300)
1726 .y(400))
1727 .build()));
1728 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1729 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1730 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1731 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1732 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1733 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1734
1735 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001737 injectMotionEvent(mDispatcher,
1738 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1739 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1740 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1741 .x(300)
1742 .y(400))
1743 .build()));
1744 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1745
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001747 injectMotionEvent(mDispatcher,
1748 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1749 AINPUT_SOURCE_MOUSE)
1750 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1751 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1752 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1753 .x(300)
1754 .y(400))
1755 .build()));
1756 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1757 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1758
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001760 injectMotionEvent(mDispatcher,
1761 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1762 AINPUT_SOURCE_MOUSE)
1763 .buttonState(0)
1764 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1765 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1766 .x(300)
1767 .y(400))
1768 .build()));
1769 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1770 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1771
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001773 injectMotionEvent(mDispatcher,
1774 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1775 .buttonState(0)
1776 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1777 .x(300)
1778 .y(400))
1779 .build()));
1780 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1781
1782 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001784 injectMotionEvent(mDispatcher,
1785 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1786 AINPUT_SOURCE_MOUSE)
1787 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1788 .x(900)
1789 .y(400))
1790 .build()));
1791 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1792 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1793 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1794 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1795 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1796 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1797}
1798
1799// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1800// directly in this test.
1801TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001802 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001803 sp<FakeWindowHandle> window =
1804 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1805 window->setFrame(Rect(0, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001806 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001807
1808 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1809
1810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1811
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001813 injectMotionEvent(mDispatcher,
1814 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1815 AINPUT_SOURCE_MOUSE)
1816 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1817 .x(300)
1818 .y(400))
1819 .build()));
1820 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1821 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1822
1823 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001825 injectMotionEvent(mDispatcher,
1826 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1827 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1828 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1829 .x(300)
1830 .y(400))
1831 .build()));
1832 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1833
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001835 injectMotionEvent(mDispatcher,
1836 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1837 AINPUT_SOURCE_MOUSE)
1838 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1839 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1840 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1841 .x(300)
1842 .y(400))
1843 .build()));
1844 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1845 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1846
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001848 injectMotionEvent(mDispatcher,
1849 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1850 AINPUT_SOURCE_MOUSE)
1851 .buttonState(0)
1852 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1853 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1854 .x(300)
1855 .y(400))
1856 .build()));
1857 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1858 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1859
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001861 injectMotionEvent(mDispatcher,
1862 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1863 .buttonState(0)
1864 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1865 .x(300)
1866 .y(400))
1867 .build()));
1868 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1869
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001871 injectMotionEvent(mDispatcher,
1872 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1873 AINPUT_SOURCE_MOUSE)
1874 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1875 .x(300)
1876 .y(400))
1877 .build()));
1878 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1879 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1880}
1881
Garfield Tan00f511d2019-06-12 16:55:40 -07001882TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001884
1885 sp<FakeWindowHandle> windowLeft =
1886 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1887 windowLeft->setFrame(Rect(0, 0, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001888 windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001889 sp<FakeWindowHandle> windowRight =
1890 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1891 windowRight->setFrame(Rect(600, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001892 windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001893
1894 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1895
Arthur Hung72d8dc32020-03-28 00:48:39 +00001896 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001897
1898 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1899 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001901 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001902 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001903 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001904 windowRight->assertNoEvents();
1905}
1906
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001907TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001909 sp<FakeWindowHandle> window =
1910 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001911 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001912
Arthur Hung72d8dc32020-03-28 00:48:39 +00001913 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001914 setFocusedWindow(window);
1915
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001916 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001917
1918 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1919 mDispatcher->notifyKey(&keyArgs);
1920
1921 // Window should receive key down event.
1922 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1923
1924 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1925 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001926 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001927 mDispatcher->notifyDeviceReset(&args);
1928 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1929 AKEY_EVENT_FLAG_CANCELED);
1930}
1931
1932TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001933 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001934 sp<FakeWindowHandle> window =
1935 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1936
Arthur Hung72d8dc32020-03-28 00:48:39 +00001937 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001938
1939 NotifyMotionArgs motionArgs =
1940 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1941 ADISPLAY_ID_DEFAULT);
1942 mDispatcher->notifyMotion(&motionArgs);
1943
1944 // Window should receive motion down event.
1945 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1946
1947 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1948 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001949 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001950 mDispatcher->notifyDeviceReset(&args);
1951 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1952 0 /*expectedFlags*/);
1953}
1954
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001955using TransferFunction =
1956 std::function<bool(sp<InputDispatcher> dispatcher, sp<IBinder>, sp<IBinder>)>;
1957
1958class TransferTouchFixture : public InputDispatcherTest,
1959 public ::testing::WithParamInterface<TransferFunction> {};
1960
1961TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001962 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001963
1964 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001965 sp<FakeWindowHandle> firstWindow =
1966 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1967 sp<FakeWindowHandle> secondWindow =
1968 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001969
1970 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001971 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001972
1973 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001974 NotifyMotionArgs downMotionArgs =
1975 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1976 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001977 mDispatcher->notifyMotion(&downMotionArgs);
1978 // Only the first window should get the down event
1979 firstWindow->consumeMotionDown();
1980 secondWindow->assertNoEvents();
1981
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001982 // Transfer touch to the second window
1983 TransferFunction f = GetParam();
1984 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
1985 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001986 // The first window gets cancel and the second gets down
1987 firstWindow->consumeMotionCancel();
1988 secondWindow->consumeMotionDown();
1989
1990 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001991 NotifyMotionArgs upMotionArgs =
1992 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1993 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001994 mDispatcher->notifyMotion(&upMotionArgs);
1995 // The first window gets no events and the second gets up
1996 firstWindow->assertNoEvents();
1997 secondWindow->consumeMotionUp();
1998}
1999
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002000TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002002
2003 PointF touchPoint = {10, 10};
2004
2005 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002006 sp<FakeWindowHandle> firstWindow =
2007 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2008 sp<FakeWindowHandle> secondWindow =
2009 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002010
2011 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002012 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002013
2014 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002015 NotifyMotionArgs downMotionArgs =
2016 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2017 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002018 mDispatcher->notifyMotion(&downMotionArgs);
2019 // Only the first window should get the down event
2020 firstWindow->consumeMotionDown();
2021 secondWindow->assertNoEvents();
2022
2023 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002024 NotifyMotionArgs pointerDownMotionArgs =
2025 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2026 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2027 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2028 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002029 mDispatcher->notifyMotion(&pointerDownMotionArgs);
2030 // Only the first window should get the pointer down event
2031 firstWindow->consumeMotionPointerDown(1);
2032 secondWindow->assertNoEvents();
2033
2034 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002035 TransferFunction f = GetParam();
2036 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2037 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002038 // The first window gets cancel and the second gets down and pointer down
2039 firstWindow->consumeMotionCancel();
2040 secondWindow->consumeMotionDown();
2041 secondWindow->consumeMotionPointerDown(1);
2042
2043 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002044 NotifyMotionArgs pointerUpMotionArgs =
2045 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2046 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2047 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2048 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002049 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2050 // The first window gets nothing and the second gets pointer up
2051 firstWindow->assertNoEvents();
2052 secondWindow->consumeMotionPointerUp(1);
2053
2054 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002055 NotifyMotionArgs upMotionArgs =
2056 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2057 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002058 mDispatcher->notifyMotion(&upMotionArgs);
2059 // The first window gets nothing and the second gets up
2060 firstWindow->assertNoEvents();
2061 secondWindow->consumeMotionUp();
2062}
2063
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002064// For the cases of single pointer touch and two pointers non-split touch, the api's
2065// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
2066// for the case where there are multiple pointers split across several windows.
2067INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
2068 ::testing::Values(
2069 [&](sp<InputDispatcher> dispatcher, sp<IBinder> /*ignored*/,
2070 sp<IBinder> destChannelToken) {
2071 return dispatcher->transferTouch(destChannelToken);
2072 },
2073 [&](sp<InputDispatcher> dispatcher, sp<IBinder> from,
2074 sp<IBinder> to) {
2075 return dispatcher->transferTouchFocus(from, to,
2076 false /*isDragAndDrop*/);
2077 }));
2078
Svet Ganov5d3bc372020-01-26 23:11:07 -08002079TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002080 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002081
2082 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002083 sp<FakeWindowHandle> firstWindow =
2084 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002085 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002086 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002087
2088 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002089 sp<FakeWindowHandle> secondWindow =
2090 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002091 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002092 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002093
2094 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002095 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002096
2097 PointF pointInFirst = {300, 200};
2098 PointF pointInSecond = {300, 600};
2099
2100 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002101 NotifyMotionArgs firstDownMotionArgs =
2102 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2103 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002104 mDispatcher->notifyMotion(&firstDownMotionArgs);
2105 // Only the first window should get the down event
2106 firstWindow->consumeMotionDown();
2107 secondWindow->assertNoEvents();
2108
2109 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002110 NotifyMotionArgs secondDownMotionArgs =
2111 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2112 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2113 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2114 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002115 mDispatcher->notifyMotion(&secondDownMotionArgs);
2116 // The first window gets a move and the second a down
2117 firstWindow->consumeMotionMove();
2118 secondWindow->consumeMotionDown();
2119
2120 // Transfer touch focus to the second window
2121 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
2122 // The first window gets cancel and the new gets pointer down (it already saw down)
2123 firstWindow->consumeMotionCancel();
2124 secondWindow->consumeMotionPointerDown(1);
2125
2126 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002127 NotifyMotionArgs pointerUpMotionArgs =
2128 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2129 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2130 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2131 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002132 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2133 // The first window gets nothing and the second gets pointer up
2134 firstWindow->assertNoEvents();
2135 secondWindow->consumeMotionPointerUp(1);
2136
2137 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002138 NotifyMotionArgs upMotionArgs =
2139 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2140 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002141 mDispatcher->notifyMotion(&upMotionArgs);
2142 // The first window gets nothing and the second gets up
2143 firstWindow->assertNoEvents();
2144 secondWindow->consumeMotionUp();
2145}
2146
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002147// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
2148// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
2149// touch is not supported, so the touch should continue on those windows and the transferred-to
2150// window should get nothing.
2151TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
2152 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2153
2154 // Create a non touch modal window that supports split touch
2155 sp<FakeWindowHandle> firstWindow =
2156 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2157 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002158 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002159
2160 // Create a non touch modal window that supports split touch
2161 sp<FakeWindowHandle> secondWindow =
2162 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2163 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002164 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002165
2166 // Add the windows to the dispatcher
2167 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2168
2169 PointF pointInFirst = {300, 200};
2170 PointF pointInSecond = {300, 600};
2171
2172 // Send down to the first window
2173 NotifyMotionArgs firstDownMotionArgs =
2174 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2175 ADISPLAY_ID_DEFAULT, {pointInFirst});
2176 mDispatcher->notifyMotion(&firstDownMotionArgs);
2177 // Only the first window should get the down event
2178 firstWindow->consumeMotionDown();
2179 secondWindow->assertNoEvents();
2180
2181 // Send down to the second window
2182 NotifyMotionArgs secondDownMotionArgs =
2183 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2184 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2185 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2186 {pointInFirst, pointInSecond});
2187 mDispatcher->notifyMotion(&secondDownMotionArgs);
2188 // The first window gets a move and the second a down
2189 firstWindow->consumeMotionMove();
2190 secondWindow->consumeMotionDown();
2191
2192 // Transfer touch focus to the second window
2193 const bool transferred = mDispatcher->transferTouch(secondWindow->getToken());
2194 // The 'transferTouch' call should not succeed, because there are 2 touched windows
2195 ASSERT_FALSE(transferred);
2196 firstWindow->assertNoEvents();
2197 secondWindow->assertNoEvents();
2198
2199 // The rest of the dispatch should proceed as normal
2200 // Send pointer up to the second window
2201 NotifyMotionArgs pointerUpMotionArgs =
2202 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2203 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2204 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2205 {pointInFirst, pointInSecond});
2206 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2207 // The first window gets MOVE and the second gets pointer up
2208 firstWindow->consumeMotionMove();
2209 secondWindow->consumeMotionUp();
2210
2211 // Send up event to the first window
2212 NotifyMotionArgs upMotionArgs =
2213 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2214 ADISPLAY_ID_DEFAULT);
2215 mDispatcher->notifyMotion(&upMotionArgs);
2216 // The first window gets nothing and the second gets up
2217 firstWindow->consumeMotionUp();
2218 secondWindow->assertNoEvents();
2219}
2220
Arthur Hungabbb9d82021-09-01 14:52:30 +00002221// This case will create two windows and one mirrored window on the default display and mirror
2222// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
2223// the windows info of second display before default display.
2224TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
2225 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2226 sp<FakeWindowHandle> firstWindowInPrimary =
2227 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2228 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
2229 firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2230 sp<FakeWindowHandle> secondWindowInPrimary =
2231 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2232 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2233 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2234
2235 sp<FakeWindowHandle> mirrorWindowInPrimary =
2236 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2237 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
2238 mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2239
2240 sp<FakeWindowHandle> firstWindowInSecondary =
2241 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2242 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
2243 firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2244
2245 sp<FakeWindowHandle> secondWindowInSecondary =
2246 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2247 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2248 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2249
2250 // Update window info, let it find window handle of second display first.
2251 mDispatcher->setInputWindows(
2252 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2253 {ADISPLAY_ID_DEFAULT,
2254 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2255
2256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2257 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2258 {50, 50}))
2259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2260
2261 // Window should receive motion event.
2262 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2263
2264 // Transfer touch focus
2265 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
2266 secondWindowInPrimary->getToken()));
2267 // The first window gets cancel.
2268 firstWindowInPrimary->consumeMotionCancel();
2269 secondWindowInPrimary->consumeMotionDown();
2270
2271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2272 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2273 ADISPLAY_ID_DEFAULT, {150, 50}))
2274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2275 firstWindowInPrimary->assertNoEvents();
2276 secondWindowInPrimary->consumeMotionMove();
2277
2278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2279 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2280 {150, 50}))
2281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2282 firstWindowInPrimary->assertNoEvents();
2283 secondWindowInPrimary->consumeMotionUp();
2284}
2285
2286// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
2287// 'transferTouch' api.
2288TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
2289 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2290 sp<FakeWindowHandle> firstWindowInPrimary =
2291 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2292 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
2293 firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2294 sp<FakeWindowHandle> secondWindowInPrimary =
2295 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2296 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2297 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2298
2299 sp<FakeWindowHandle> mirrorWindowInPrimary =
2300 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2301 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
2302 mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2303
2304 sp<FakeWindowHandle> firstWindowInSecondary =
2305 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2306 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
2307 firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2308
2309 sp<FakeWindowHandle> secondWindowInSecondary =
2310 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2311 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2312 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2313
2314 // Update window info, let it find window handle of second display first.
2315 mDispatcher->setInputWindows(
2316 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2317 {ADISPLAY_ID_DEFAULT,
2318 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2319
2320 // Touch on second display.
2321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2322 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
2323 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2324
2325 // Window should receive motion event.
2326 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2327
2328 // Transfer touch focus
2329 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken()));
2330
2331 // The first window gets cancel.
2332 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
2333 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2334
2335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2336 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2337 SECOND_DISPLAY_ID, {150, 50}))
2338 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2339 firstWindowInPrimary->assertNoEvents();
2340 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
2341
2342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2343 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
2344 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2345 firstWindowInPrimary->assertNoEvents();
2346 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
2347}
2348
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002349TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002350 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002351 sp<FakeWindowHandle> window =
2352 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2353
Vishnu Nair47074b82020-08-14 11:54:47 -07002354 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002355 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002356 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002357
2358 window->consumeFocusEvent(true);
2359
2360 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2361 mDispatcher->notifyKey(&keyArgs);
2362
2363 // Window should receive key down event.
2364 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2365}
2366
2367TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002369 sp<FakeWindowHandle> window =
2370 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2371
Arthur Hung72d8dc32020-03-28 00:48:39 +00002372 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002373
2374 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2375 mDispatcher->notifyKey(&keyArgs);
2376 mDispatcher->waitForIdle();
2377
2378 window->assertNoEvents();
2379}
2380
2381// If a window is touchable, but does not have focus, it should receive motion events, but not keys
2382TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07002383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002384 sp<FakeWindowHandle> window =
2385 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2386
Arthur Hung72d8dc32020-03-28 00:48:39 +00002387 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002388
2389 // Send key
2390 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2391 mDispatcher->notifyKey(&keyArgs);
2392 // Send motion
2393 NotifyMotionArgs motionArgs =
2394 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2395 ADISPLAY_ID_DEFAULT);
2396 mDispatcher->notifyMotion(&motionArgs);
2397
2398 // Window should receive only the motion event
2399 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2400 window->assertNoEvents(); // Key event or focus event will not be received
2401}
2402
arthurhungea3f4fc2020-12-21 23:18:53 +08002403TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
2404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2405
2406 // Create first non touch modal window that supports split touch
2407 sp<FakeWindowHandle> firstWindow =
2408 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2409 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002410 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
arthurhungea3f4fc2020-12-21 23:18:53 +08002411
2412 // Create second non touch modal window that supports split touch
2413 sp<FakeWindowHandle> secondWindow =
2414 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2415 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002416 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
arthurhungea3f4fc2020-12-21 23:18:53 +08002417
2418 // Add the windows to the dispatcher
2419 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2420
2421 PointF pointInFirst = {300, 200};
2422 PointF pointInSecond = {300, 600};
2423
2424 // Send down to the first window
2425 NotifyMotionArgs firstDownMotionArgs =
2426 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2427 ADISPLAY_ID_DEFAULT, {pointInFirst});
2428 mDispatcher->notifyMotion(&firstDownMotionArgs);
2429 // Only the first window should get the down event
2430 firstWindow->consumeMotionDown();
2431 secondWindow->assertNoEvents();
2432
2433 // Send down to the second window
2434 NotifyMotionArgs secondDownMotionArgs =
2435 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2436 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2437 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2438 {pointInFirst, pointInSecond});
2439 mDispatcher->notifyMotion(&secondDownMotionArgs);
2440 // The first window gets a move and the second a down
2441 firstWindow->consumeMotionMove();
2442 secondWindow->consumeMotionDown();
2443
2444 // Send pointer cancel to the second window
2445 NotifyMotionArgs pointerUpMotionArgs =
2446 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2447 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2448 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2449 {pointInFirst, pointInSecond});
2450 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
2451 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2452 // The first window gets move and the second gets cancel.
2453 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2454 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2455
2456 // Send up event.
2457 NotifyMotionArgs upMotionArgs =
2458 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2459 ADISPLAY_ID_DEFAULT);
2460 mDispatcher->notifyMotion(&upMotionArgs);
2461 // The first window gets up and the second gets nothing.
2462 firstWindow->consumeMotionUp();
2463 secondWindow->assertNoEvents();
2464}
2465
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00002466TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
2467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2468
2469 sp<FakeWindowHandle> window =
2470 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2471 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2472 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
2473 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
2474 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
2475
2476 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
2477 window->assertNoEvents();
2478 mDispatcher->waitForIdle();
2479}
2480
chaviwd1c23182019-12-20 18:44:56 -08002481class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00002482public:
2483 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08002484 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07002485 base::Result<std::unique_ptr<InputChannel>> channel =
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +00002486 dispatcher->createInputMonitor(displayId, isGestureMonitor, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07002487 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00002488 }
2489
chaviwd1c23182019-12-20 18:44:56 -08002490 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
2491
2492 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2493 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
2494 expectedDisplayId, expectedFlags);
2495 }
2496
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002497 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
2498
2499 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
2500
chaviwd1c23182019-12-20 18:44:56 -08002501 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2502 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
2503 expectedDisplayId, expectedFlags);
2504 }
2505
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002506 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2507 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
2508 expectedDisplayId, expectedFlags);
2509 }
2510
chaviwd1c23182019-12-20 18:44:56 -08002511 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2512 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
2513 expectedDisplayId, expectedFlags);
2514 }
2515
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002516 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2517 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2518 expectedDisplayId, expectedFlags);
2519 }
2520
Evan Rosky84f07f02021-04-16 10:42:42 -07002521 MotionEvent* consumeMotion() {
2522 InputEvent* event = mInputReceiver->consume();
2523 if (!event) {
2524 ADD_FAILURE() << "No event was produced";
2525 return nullptr;
2526 }
2527 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
2528 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
2529 return nullptr;
2530 }
2531 return static_cast<MotionEvent*>(event);
2532 }
2533
chaviwd1c23182019-12-20 18:44:56 -08002534 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
2535
2536private:
2537 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00002538};
2539
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002540/**
2541 * Two entities that receive touch: A window, and a global monitor.
2542 * The touch goes to the window, and then the window disappears.
2543 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
2544 * for the monitor, as well.
2545 * 1. foregroundWindow
2546 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
2547 */
2548TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_GlobalMonitorTouchIsCanceled) {
2549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2550 sp<FakeWindowHandle> window =
2551 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2552
2553 FakeMonitorReceiver monitor =
2554 FakeMonitorReceiver(mDispatcher, "GlobalMonitor", ADISPLAY_ID_DEFAULT,
2555 false /*isGestureMonitor*/);
2556
2557 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2559 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2560 {100, 200}))
2561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2562
2563 // Both the foreground window and the global monitor should receive the touch down
2564 window->consumeMotionDown();
2565 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2566
2567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2568 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2569 ADISPLAY_ID_DEFAULT, {110, 200}))
2570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2571
2572 window->consumeMotionMove();
2573 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
2574
2575 // Now the foreground window goes away
2576 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2577 window->consumeMotionCancel();
2578 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
2579
2580 // If more events come in, there will be no more foreground window to send them to. This will
2581 // cause a cancel for the monitor, as well.
2582 ASSERT_EQ(InputEventInjectionResult::FAILED,
2583 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2584 ADISPLAY_ID_DEFAULT, {120, 200}))
2585 << "Injection should fail because the window was removed";
2586 window->assertNoEvents();
2587 // Global monitor now gets the cancel
2588 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
2589}
2590
Michael Wright3a240c42019-12-10 20:53:41 +00002591// Tests for gesture monitors
2592TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002594 sp<FakeWindowHandle> window =
2595 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002596 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002597
chaviwd1c23182019-12-20 18:44:56 -08002598 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2599 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002600
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002602 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002603 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002604 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002605 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002606}
2607
2608TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002609 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002610 sp<FakeWindowHandle> window =
2611 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2612
2613 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002614 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00002615
Arthur Hung72d8dc32020-03-28 00:48:39 +00002616 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002617 setFocusedWindow(window);
2618
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002619 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00002620
chaviwd1c23182019-12-20 18:44:56 -08002621 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2622 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002623
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2625 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002626 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002627 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00002628}
2629
2630TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002631 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002632 sp<FakeWindowHandle> window =
2633 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002635
chaviwd1c23182019-12-20 18:44:56 -08002636 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2637 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002638
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002640 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002642 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002643 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002644
2645 window->releaseChannel();
2646
chaviwd1c23182019-12-20 18:44:56 -08002647 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00002648
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002650 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08002652 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002653}
2654
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002655TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
2656 FakeMonitorReceiver monitor =
2657 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2658 true /*isGestureMonitor*/);
2659
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002661 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
2662 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
2663 ASSERT_TRUE(consumeSeq);
2664
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002665 mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002666 monitor.finishEvent(*consumeSeq);
2667 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002668 mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002669}
2670
Evan Rosky84f07f02021-04-16 10:42:42 -07002671// Tests for gesture monitors
2672TEST_F(InputDispatcherTest, GestureMonitor_NoWindowTransform) {
2673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2674 sp<FakeWindowHandle> window =
2675 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2676 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2677 window->setWindowOffset(20, 40);
2678 window->setWindowTransform(0, 1, -1, 0);
2679
2680 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2681 true /*isGestureMonitor*/);
2682
2683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2684 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2686 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2687 MotionEvent* event = monitor.consumeMotion();
2688 // Even though window has transform, gesture monitor must not.
2689 ASSERT_EQ(ui::Transform(), event->getTransform());
2690}
2691
chaviw81e2bb92019-12-18 15:03:51 -08002692TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08002694 sp<FakeWindowHandle> window =
2695 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2696
Arthur Hung72d8dc32020-03-28 00:48:39 +00002697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08002698
2699 NotifyMotionArgs motionArgs =
2700 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2701 ADISPLAY_ID_DEFAULT);
2702
2703 mDispatcher->notifyMotion(&motionArgs);
2704 // Window should receive motion down event.
2705 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2706
2707 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002708 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08002709 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2710 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
2711 motionArgs.pointerCoords[0].getX() - 10);
2712
2713 mDispatcher->notifyMotion(&motionArgs);
2714 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
2715 0 /*expectedFlags*/);
2716}
2717
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002718/**
2719 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
2720 * the device default right away. In the test scenario, we check both the default value,
2721 * and the action of enabling / disabling.
2722 */
2723TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07002724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002725 sp<FakeWindowHandle> window =
2726 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2727
2728 // Set focused application.
2729 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002730 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002731
2732 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00002733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002734 setFocusedWindow(window);
2735
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002736 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2737
2738 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002739 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002740 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002741 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
2742
2743 SCOPED_TRACE("Disable touch mode");
2744 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07002745 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002746 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002747 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002748 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
2749
2750 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002751 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002753 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
2754
2755 SCOPED_TRACE("Enable touch mode again");
2756 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07002757 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002759 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002760 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2761
2762 window->assertNoEvents();
2763}
2764
Gang Wange9087892020-01-07 12:17:14 -05002765TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05002767 sp<FakeWindowHandle> window =
2768 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2769
2770 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002771 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05002772
Arthur Hung72d8dc32020-03-28 00:48:39 +00002773 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002774 setFocusedWindow(window);
2775
Gang Wange9087892020-01-07 12:17:14 -05002776 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2777
2778 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2779 mDispatcher->notifyKey(&keyArgs);
2780
2781 InputEvent* event = window->consume();
2782 ASSERT_NE(event, nullptr);
2783
2784 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2785 ASSERT_NE(verified, nullptr);
2786 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
2787
2788 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
2789 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
2790 ASSERT_EQ(keyArgs.source, verified->source);
2791 ASSERT_EQ(keyArgs.displayId, verified->displayId);
2792
2793 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
2794
2795 ASSERT_EQ(keyArgs.action, verifiedKey.action);
2796 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05002797 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
2798 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
2799 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
2800 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
2801 ASSERT_EQ(0, verifiedKey.repeatCount);
2802}
2803
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002804TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002806 sp<FakeWindowHandle> window =
2807 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2808
2809 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2810
Arthur Hung72d8dc32020-03-28 00:48:39 +00002811 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002812
2813 NotifyMotionArgs motionArgs =
2814 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2815 ADISPLAY_ID_DEFAULT);
2816 mDispatcher->notifyMotion(&motionArgs);
2817
2818 InputEvent* event = window->consume();
2819 ASSERT_NE(event, nullptr);
2820
2821 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2822 ASSERT_NE(verified, nullptr);
2823 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2824
2825 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2826 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2827 EXPECT_EQ(motionArgs.source, verified->source);
2828 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2829
2830 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2831
2832 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2833 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2834 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2835 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2836 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2837 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2838 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2839}
2840
Prabir Pradhan664834b2021-05-20 16:00:42 -07002841TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickAndTouchpadNotTransformed) {
yunho.shinf4a80b82020-11-16 21:13:57 +09002842 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2843 sp<FakeWindowHandle> window =
2844 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2845 const std::string name = window->getName();
2846
2847 // Window gets transformed by offset values.
2848 window->setWindowOffset(500.0f, 500.0f);
2849
2850 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2851 window->setFocusable(true);
2852
2853 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2854
2855 // First, we set focused window so that focusedWindowHandle is not null.
2856 setFocusedWindow(window);
2857
2858 // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
2859 window->consumeFocusEvent(true);
2860
Prabir Pradhan664834b2021-05-20 16:00:42 -07002861 constexpr const std::array nonTransformedSources = {std::pair(AINPUT_SOURCE_TOUCHPAD,
2862 AMOTION_EVENT_ACTION_DOWN),
2863 std::pair(AINPUT_SOURCE_JOYSTICK,
2864 AMOTION_EVENT_ACTION_MOVE)};
2865 for (const auto& [source, action] : nonTransformedSources) {
2866 const NotifyMotionArgs motionArgs = generateMotionArgs(action, source, ADISPLAY_ID_DEFAULT);
Prabir Pradhanbd527712021-03-09 19:17:09 -08002867 mDispatcher->notifyMotion(&motionArgs);
yunho.shinf4a80b82020-11-16 21:13:57 +09002868
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002869 MotionEvent* event = window->consumeMotion();
Prabir Pradhanbd527712021-03-09 19:17:09 -08002870 ASSERT_NE(event, nullptr);
yunho.shinf4a80b82020-11-16 21:13:57 +09002871
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002872 const MotionEvent& motionEvent = *event;
Prabir Pradhan664834b2021-05-20 16:00:42 -07002873 EXPECT_EQ(action, motionEvent.getAction());
Prabir Pradhanbd527712021-03-09 19:17:09 -08002874 EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
yunho.shinf4a80b82020-11-16 21:13:57 +09002875
Prabir Pradhanbd527712021-03-09 19:17:09 -08002876 float expectedX = motionArgs.pointerCoords[0].getX();
2877 float expectedY = motionArgs.pointerCoords[0].getY();
yunho.shinf4a80b82020-11-16 21:13:57 +09002878
Prabir Pradhanbd527712021-03-09 19:17:09 -08002879 // Ensure the axis values from the final motion event are not transformed.
2880 EXPECT_EQ(expectedX, motionEvent.getX(0))
2881 << "expected " << expectedX << " for x coord of " << name.c_str() << ", got "
2882 << motionEvent.getX(0);
2883 EXPECT_EQ(expectedY, motionEvent.getY(0))
2884 << "expected " << expectedY << " for y coord of " << name.c_str() << ", got "
2885 << motionEvent.getY(0);
2886 // Ensure the raw and transformed axis values for the motion event are the same.
2887 EXPECT_EQ(motionEvent.getRawX(0), motionEvent.getX(0))
2888 << "expected raw and transformed X-axis values to be equal";
2889 EXPECT_EQ(motionEvent.getRawY(0), motionEvent.getY(0))
2890 << "expected raw and transformed Y-axis values to be equal";
2891 }
yunho.shinf4a80b82020-11-16 21:13:57 +09002892}
2893
chaviw09c8d2d2020-08-24 15:48:26 -07002894/**
2895 * Ensure that separate calls to sign the same data are generating the same key.
2896 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2897 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2898 * tests.
2899 */
2900TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2901 KeyEvent event = getTestKeyEvent();
2902 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2903
2904 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2905 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2906 ASSERT_EQ(hmac1, hmac2);
2907}
2908
2909/**
2910 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2911 */
2912TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2913 KeyEvent event = getTestKeyEvent();
2914 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2915 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2916
2917 verifiedEvent.deviceId += 1;
2918 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2919
2920 verifiedEvent.source += 1;
2921 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2922
2923 verifiedEvent.eventTimeNanos += 1;
2924 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2925
2926 verifiedEvent.displayId += 1;
2927 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2928
2929 verifiedEvent.action += 1;
2930 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2931
2932 verifiedEvent.downTimeNanos += 1;
2933 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2934
2935 verifiedEvent.flags += 1;
2936 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2937
2938 verifiedEvent.keyCode += 1;
2939 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2940
2941 verifiedEvent.scanCode += 1;
2942 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2943
2944 verifiedEvent.metaState += 1;
2945 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2946
2947 verifiedEvent.repeatCount += 1;
2948 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2949}
2950
Vishnu Nair958da932020-08-21 17:12:37 -07002951TEST_F(InputDispatcherTest, SetFocusedWindow) {
2952 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2953 sp<FakeWindowHandle> windowTop =
2954 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2955 sp<FakeWindowHandle> windowSecond =
2956 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2957 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2958
2959 // Top window is also focusable but is not granted focus.
2960 windowTop->setFocusable(true);
2961 windowSecond->setFocusable(true);
2962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2963 setFocusedWindow(windowSecond);
2964
2965 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2967 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002968
2969 // Focused window should receive event.
2970 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2971 windowTop->assertNoEvents();
2972}
2973
2974TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2975 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2976 sp<FakeWindowHandle> window =
2977 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2978 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2979
2980 window->setFocusable(true);
2981 // Release channel for window is no longer valid.
2982 window->releaseChannel();
2983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2984 setFocusedWindow(window);
2985
2986 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002987 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2988 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002989
2990 // window channel is invalid, so it should not receive any input event.
2991 window->assertNoEvents();
2992}
2993
2994TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2995 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2996 sp<FakeWindowHandle> window =
2997 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2998 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2999
3000 // Window is not focusable.
3001 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3002 setFocusedWindow(window);
3003
3004 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003005 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3006 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003007
3008 // window is invalid, so it should not receive any input event.
3009 window->assertNoEvents();
3010}
3011
3012TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
3013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3014 sp<FakeWindowHandle> windowTop =
3015 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3016 sp<FakeWindowHandle> windowSecond =
3017 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3018 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3019
3020 windowTop->setFocusable(true);
3021 windowSecond->setFocusable(true);
3022 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3023 setFocusedWindow(windowTop);
3024 windowTop->consumeFocusEvent(true);
3025
3026 setFocusedWindow(windowSecond, windowTop);
3027 windowSecond->consumeFocusEvent(true);
3028 windowTop->consumeFocusEvent(false);
3029
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3031 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003032
3033 // Focused window should receive event.
3034 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3035}
3036
3037TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
3038 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3039 sp<FakeWindowHandle> windowTop =
3040 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3041 sp<FakeWindowHandle> windowSecond =
3042 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3043 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3044
3045 windowTop->setFocusable(true);
3046 windowSecond->setFocusable(true);
3047 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3048 setFocusedWindow(windowSecond, windowTop);
3049
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003050 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3051 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003052
3053 // Event should be dropped.
3054 windowTop->assertNoEvents();
3055 windowSecond->assertNoEvents();
3056}
3057
3058TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
3059 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3060 sp<FakeWindowHandle> window =
3061 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3062 sp<FakeWindowHandle> previousFocusedWindow =
3063 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
3064 ADISPLAY_ID_DEFAULT);
3065 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3066
3067 window->setFocusable(true);
3068 previousFocusedWindow->setFocusable(true);
3069 window->setVisible(false);
3070 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
3071 setFocusedWindow(previousFocusedWindow);
3072 previousFocusedWindow->consumeFocusEvent(true);
3073
3074 // Requesting focus on invisible window takes focus from currently focused window.
3075 setFocusedWindow(window);
3076 previousFocusedWindow->consumeFocusEvent(false);
3077
3078 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003080 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003081 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003082
3083 // Window does not get focus event or key down.
3084 window->assertNoEvents();
3085
3086 // Window becomes visible.
3087 window->setVisible(true);
3088 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3089
3090 // Window receives focus event.
3091 window->consumeFocusEvent(true);
3092 // Focused window receives key down.
3093 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3094}
3095
Vishnu Nair599f1412021-06-21 10:39:58 -07003096TEST_F(InputDispatcherTest, DisplayRemoved) {
3097 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3098 sp<FakeWindowHandle> window =
3099 new FakeWindowHandle(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
3100 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3101
3102 // window is granted focus.
3103 window->setFocusable(true);
3104 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3105 setFocusedWindow(window);
3106 window->consumeFocusEvent(true);
3107
3108 // When a display is removed window loses focus.
3109 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
3110 window->consumeFocusEvent(false);
3111}
3112
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003113/**
3114 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
3115 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
3116 * of the 'slipperyEnterWindow'.
3117 *
3118 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
3119 * a way so that the touched location is no longer covered by the top window.
3120 *
3121 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
3122 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
3123 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
3124 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
3125 * with ACTION_DOWN).
3126 * Thus, the touch has been transferred from the top window into the bottom window, because the top
3127 * window moved itself away from the touched location and had Flag::SLIPPERY.
3128 *
3129 * Even though the top window moved away from the touched location, it is still obscuring the bottom
3130 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
3131 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
3132 *
3133 * In this test, we ensure that the event received by the bottom window has
3134 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
3135 */
3136TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
3137 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
3138 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
3139
3140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3141 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3142
3143 sp<FakeWindowHandle> slipperyExitWindow =
3144 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviw3277faf2021-05-19 16:45:23 -05003145 slipperyExitWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SLIPPERY);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003146 // Make sure this one overlaps the bottom window
3147 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
3148 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
3149 // one. Windows with the same owner are not considered to be occluding each other.
3150 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
3151
3152 sp<FakeWindowHandle> slipperyEnterWindow =
3153 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3154 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
3155
3156 mDispatcher->setInputWindows(
3157 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3158
3159 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
3160 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3161 ADISPLAY_ID_DEFAULT, {{50, 50}});
3162 mDispatcher->notifyMotion(&args);
3163 slipperyExitWindow->consumeMotionDown();
3164 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
3165 mDispatcher->setInputWindows(
3166 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3167
3168 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3169 ADISPLAY_ID_DEFAULT, {{51, 51}});
3170 mDispatcher->notifyMotion(&args);
3171
3172 slipperyExitWindow->consumeMotionCancel();
3173
3174 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
3175 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
3176}
3177
Garfield Tan1c7bc862020-01-28 13:24:04 -08003178class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
3179protected:
3180 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
3181 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
3182
Chris Yea209fde2020-07-22 13:54:51 -07003183 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003184 sp<FakeWindowHandle> mWindow;
3185
3186 virtual void SetUp() override {
3187 mFakePolicy = new FakeInputDispatcherPolicy();
3188 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
3189 mDispatcher = new InputDispatcher(mFakePolicy);
3190 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
3191 ASSERT_EQ(OK, mDispatcher->start());
3192
3193 setUpWindow();
3194 }
3195
3196 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07003197 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08003198 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
3199
Vishnu Nair47074b82020-08-14 11:54:47 -07003200 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003201 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003202 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003203 mWindow->consumeFocusEvent(true);
3204 }
3205
Chris Ye2ad95392020-09-01 13:44:44 -07003206 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003207 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003208 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003209 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
3210 mDispatcher->notifyKey(&keyArgs);
3211
3212 // Window should receive key down event.
3213 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3214 }
3215
3216 void expectKeyRepeatOnce(int32_t repeatCount) {
3217 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
3218 InputEvent* repeatEvent = mWindow->consume();
3219 ASSERT_NE(nullptr, repeatEvent);
3220
3221 uint32_t eventType = repeatEvent->getType();
3222 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
3223
3224 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
3225 uint32_t eventAction = repeatKeyEvent->getAction();
3226 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
3227 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
3228 }
3229
Chris Ye2ad95392020-09-01 13:44:44 -07003230 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003231 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003232 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003233 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
3234 mDispatcher->notifyKey(&keyArgs);
3235
3236 // Window should receive key down event.
3237 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
3238 0 /*expectedFlags*/);
3239 }
3240};
3241
3242TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07003243 sendAndConsumeKeyDown(1 /* deviceId */);
3244 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3245 expectKeyRepeatOnce(repeatCount);
3246 }
3247}
3248
3249TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
3250 sendAndConsumeKeyDown(1 /* deviceId */);
3251 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3252 expectKeyRepeatOnce(repeatCount);
3253 }
3254 sendAndConsumeKeyDown(2 /* deviceId */);
3255 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08003256 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3257 expectKeyRepeatOnce(repeatCount);
3258 }
3259}
3260
3261TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07003262 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003263 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07003264 sendAndConsumeKeyUp(1 /* deviceId */);
3265 mWindow->assertNoEvents();
3266}
3267
3268TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
3269 sendAndConsumeKeyDown(1 /* deviceId */);
3270 expectKeyRepeatOnce(1 /*repeatCount*/);
3271 sendAndConsumeKeyDown(2 /* deviceId */);
3272 expectKeyRepeatOnce(1 /*repeatCount*/);
3273 // Stale key up from device 1.
3274 sendAndConsumeKeyUp(1 /* deviceId */);
3275 // Device 2 is still down, keep repeating
3276 expectKeyRepeatOnce(2 /*repeatCount*/);
3277 expectKeyRepeatOnce(3 /*repeatCount*/);
3278 // Device 2 key up
3279 sendAndConsumeKeyUp(2 /* deviceId */);
3280 mWindow->assertNoEvents();
3281}
3282
3283TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
3284 sendAndConsumeKeyDown(1 /* deviceId */);
3285 expectKeyRepeatOnce(1 /*repeatCount*/);
3286 sendAndConsumeKeyDown(2 /* deviceId */);
3287 expectKeyRepeatOnce(1 /*repeatCount*/);
3288 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
3289 sendAndConsumeKeyUp(2 /* deviceId */);
3290 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08003291 mWindow->assertNoEvents();
3292}
3293
liushenxiang42232912021-05-21 20:24:09 +08003294TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
3295 sendAndConsumeKeyDown(DEVICE_ID);
3296 expectKeyRepeatOnce(1 /*repeatCount*/);
3297 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
3298 mDispatcher->notifyDeviceReset(&args);
3299 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
3300 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
3301 mWindow->assertNoEvents();
3302}
3303
Garfield Tan1c7bc862020-01-28 13:24:04 -08003304TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07003305 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003306 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3307 InputEvent* repeatEvent = mWindow->consume();
3308 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3309 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
3310 IdGenerator::getSource(repeatEvent->getId()));
3311 }
3312}
3313
3314TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07003315 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003316
3317 std::unordered_set<int32_t> idSet;
3318 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3319 InputEvent* repeatEvent = mWindow->consume();
3320 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3321 int32_t id = repeatEvent->getId();
3322 EXPECT_EQ(idSet.end(), idSet.find(id));
3323 idSet.insert(id);
3324 }
3325}
3326
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003327/* Test InputDispatcher for MultiDisplay */
3328class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
3329public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003330 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003331 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08003332
Chris Yea209fde2020-07-22 13:54:51 -07003333 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003334 windowInPrimary =
3335 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003336
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003337 // Set focus window for primary display, but focused display would be second one.
3338 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07003339 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003341 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003342 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08003343
Chris Yea209fde2020-07-22 13:54:51 -07003344 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003345 windowInSecondary =
3346 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003347 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003348 // Set focus display to second one.
3349 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
3350 // Set focus window for second display.
3351 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07003352 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003353 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003354 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003355 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003356 }
3357
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003358 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003359 InputDispatcherTest::TearDown();
3360
Chris Yea209fde2020-07-22 13:54:51 -07003361 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003362 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07003363 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003364 windowInSecondary.clear();
3365 }
3366
3367protected:
Chris Yea209fde2020-07-22 13:54:51 -07003368 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003369 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07003370 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003371 sp<FakeWindowHandle> windowInSecondary;
3372};
3373
3374TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
3375 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3377 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003379 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08003380 windowInSecondary->assertNoEvents();
3381
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003382 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3384 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003386 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003387 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08003388}
3389
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003390TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08003391 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3393 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003394 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003395 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08003396 windowInSecondary->assertNoEvents();
3397
3398 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003400 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003401 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003402 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08003403
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003404 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003405 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08003406
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003407 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003408 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
3409 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08003410
3411 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003412 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003413 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08003414 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003415 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08003416 windowInSecondary->assertNoEvents();
3417}
3418
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003419// Test per-display input monitors for motion event.
3420TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08003421 FakeMonitorReceiver monitorInPrimary =
3422 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3423 FakeMonitorReceiver monitorInSecondary =
3424 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003425
3426 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3428 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3429 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003430 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003431 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003432 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003433 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003434
3435 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3437 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3438 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003439 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003440 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003441 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08003442 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003443
3444 // Test inject a non-pointer motion event.
3445 // If specific a display, it will dispatch to the focused window of particular display,
3446 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3448 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
3449 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003450 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003451 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003452 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003453 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003454}
3455
3456// Test per-display input monitors for key event.
3457TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003458 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08003459 FakeMonitorReceiver monitorInPrimary =
3460 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3461 FakeMonitorReceiver monitorInSecondary =
3462 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003463
3464 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3466 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003467 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003468 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003469 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003470 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003471}
3472
Vishnu Nair958da932020-08-21 17:12:37 -07003473TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
3474 sp<FakeWindowHandle> secondWindowInPrimary =
3475 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
3476 secondWindowInPrimary->setFocusable(true);
3477 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
3478 setFocusedWindow(secondWindowInPrimary);
3479 windowInPrimary->consumeFocusEvent(false);
3480 secondWindowInPrimary->consumeFocusEvent(true);
3481
3482 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
3484 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003485 windowInPrimary->assertNoEvents();
3486 windowInSecondary->assertNoEvents();
3487 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3488}
3489
Jackal Guof9696682018-10-05 12:23:23 +08003490class InputFilterTest : public InputDispatcherTest {
3491protected:
Jackal Guof9696682018-10-05 12:23:23 +08003492 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
3493 NotifyMotionArgs motionArgs;
3494
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003495 motionArgs =
3496 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003497 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003498 motionArgs =
3499 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003500 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003501 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003502 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003503 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003504 } else {
3505 mFakePolicy->assertFilterInputEventWasNotCalled();
3506 }
3507 }
3508
3509 void testNotifyKey(bool expectToBeFiltered) {
3510 NotifyKeyArgs keyArgs;
3511
3512 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3513 mDispatcher->notifyKey(&keyArgs);
3514 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
3515 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003516 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003517
3518 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003519 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003520 } else {
3521 mFakePolicy->assertFilterInputEventWasNotCalled();
3522 }
3523 }
3524};
3525
3526// Test InputFilter for MotionEvent
3527TEST_F(InputFilterTest, MotionEvent_InputFilter) {
3528 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
3529 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3530 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3531
3532 // Enable InputFilter
3533 mDispatcher->setInputFilterEnabled(true);
3534 // Test touch on both primary and second display, and check if both events are filtered.
3535 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
3536 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
3537
3538 // Disable InputFilter
3539 mDispatcher->setInputFilterEnabled(false);
3540 // Test touch on both primary and second display, and check if both events aren't filtered.
3541 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3542 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3543}
3544
3545// Test InputFilter for KeyEvent
3546TEST_F(InputFilterTest, KeyEvent_InputFilter) {
3547 // Since the InputFilter is disabled by default, check if key event aren't filtered.
3548 testNotifyKey(/*expectToBeFiltered*/ false);
3549
3550 // Enable InputFilter
3551 mDispatcher->setInputFilterEnabled(true);
3552 // Send a key event, and check if it is filtered.
3553 testNotifyKey(/*expectToBeFiltered*/ true);
3554
3555 // Disable InputFilter
3556 mDispatcher->setInputFilterEnabled(false);
3557 // Send a key event, and check if it isn't filtered.
3558 testNotifyKey(/*expectToBeFiltered*/ false);
3559}
3560
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003561class InputFilterInjectionPolicyTest : public InputDispatcherTest {
3562protected:
3563 virtual void SetUp() override {
3564 InputDispatcherTest::SetUp();
3565
3566 /**
3567 * We don't need to enable input filter to test the injected event policy, but we enabled it
3568 * here to make the tests more realistic, since this policy only matters when inputfilter is
3569 * on.
3570 */
3571 mDispatcher->setInputFilterEnabled(true);
3572
3573 std::shared_ptr<InputApplicationHandle> application =
3574 std::make_shared<FakeApplicationHandle>();
3575 mWindow =
3576 new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT);
3577
3578 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3579 mWindow->setFocusable(true);
3580 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3581 setFocusedWindow(mWindow);
3582 mWindow->consumeFocusEvent(true);
3583 }
3584
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003585 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3586 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003587 KeyEvent event;
3588
3589 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3590 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
3591 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
3592 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
3593 const int32_t additionalPolicyFlags =
3594 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
3595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3596 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3597 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3598 policyFlags | additionalPolicyFlags));
3599
3600 InputEvent* received = mWindow->consume();
3601 ASSERT_NE(nullptr, received);
3602 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003603 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
3604 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
3605 ASSERT_EQ(flags, keyEvent.getFlags());
3606 }
3607
3608 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3609 int32_t flags) {
3610 MotionEvent event;
3611 PointerProperties pointerProperties[1];
3612 PointerCoords pointerCoords[1];
3613 pointerProperties[0].clear();
3614 pointerProperties[0].id = 0;
3615 pointerCoords[0].clear();
3616 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
3617 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
3618
3619 ui::Transform identityTransform;
3620 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3621 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
3622 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
3623 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
3624 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -07003625 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
3626 0 /*INVALID_DISPLAY_SIZE*/, 0 /*INVALID_DISPLAY_SIZE*/, eventTime,
3627 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003628 /*pointerCount*/ 1, pointerProperties, pointerCoords);
3629
3630 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
3631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3632 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3633 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3634 policyFlags | additionalPolicyFlags));
3635
3636 InputEvent* received = mWindow->consume();
3637 ASSERT_NE(nullptr, received);
3638 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
3639 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
3640 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
3641 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003642 }
3643
3644private:
3645 sp<FakeWindowHandle> mWindow;
3646};
3647
3648TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003649 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
3650 // filter. Without it, the event will no different from a regularly injected event, and the
3651 // injected device id will be overwritten.
3652 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3653 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003654}
3655
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003656TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003657 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003658 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3659 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3660}
3661
3662TEST_F(InputFilterInjectionPolicyTest,
3663 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
3664 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
3665 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3666 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003667}
3668
3669TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
3670 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003671 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003672}
3673
chaviwfd6d3512019-03-25 13:23:49 -07003674class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003675 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07003676 InputDispatcherTest::SetUp();
3677
Chris Yea209fde2020-07-22 13:54:51 -07003678 std::shared_ptr<FakeApplicationHandle> application =
3679 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003680 mUnfocusedWindow =
3681 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003682 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3683 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3684 // window.
chaviw3277faf2021-05-19 16:45:23 -05003685 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003686
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003687 mFocusedWindow =
3688 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3689 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05003690 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003691
3692 // Set focused application.
3693 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003694 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07003695
3696 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003698 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003699 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07003700 }
3701
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003702 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07003703 InputDispatcherTest::TearDown();
3704
3705 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003706 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07003707 }
3708
3709protected:
3710 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003711 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003712 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07003713};
3714
3715// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3716// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
3717// the onPointerDownOutsideFocus callback.
3718TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003720 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3721 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003723 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003724
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003725 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07003726 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
3727}
3728
3729// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
3730// DOWN on the window that doesn't have focus. Ensure no window received the
3731// onPointerDownOutsideFocus callback.
3732TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003734 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003736 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003737
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003738 ASSERT_TRUE(mDispatcher->waitForIdle());
3739 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003740}
3741
3742// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
3743// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
3744TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3746 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003747 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003748 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003749
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003750 ASSERT_TRUE(mDispatcher->waitForIdle());
3751 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003752}
3753
3754// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3755// DOWN on the window that already has focus. Ensure no window received the
3756// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003757TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003759 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003760 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003762 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003763
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003764 ASSERT_TRUE(mDispatcher->waitForIdle());
3765 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003766}
3767
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08003768// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
3769// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
3770TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
3771 const MotionEvent event =
3772 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3773 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
3774 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
3775 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
3776 .build();
3777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
3778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3779 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
3780
3781 ASSERT_TRUE(mDispatcher->waitForIdle());
3782 mFakePolicy->assertOnPointerDownWasNotCalled();
3783 // Ensure that the unfocused window did not receive any FOCUS events.
3784 mUnfocusedWindow->assertNoEvents();
3785}
3786
chaviwaf87b3e2019-10-01 16:59:28 -07003787// These tests ensures we can send touch events to a single client when there are multiple input
3788// windows that point to the same client token.
3789class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
3790 virtual void SetUp() override {
3791 InputDispatcherTest::SetUp();
3792
Chris Yea209fde2020-07-22 13:54:51 -07003793 std::shared_ptr<FakeApplicationHandle> application =
3794 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07003795 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
3796 ADISPLAY_ID_DEFAULT);
3797 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
3798 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
chaviw3277faf2021-05-19 16:45:23 -05003799 mWindow1->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003800 mWindow1->setFrame(Rect(0, 0, 100, 100));
3801
3802 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
3803 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviw3277faf2021-05-19 16:45:23 -05003804 mWindow2->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003805 mWindow2->setFrame(Rect(100, 100, 200, 200));
3806
Arthur Hung72d8dc32020-03-28 00:48:39 +00003807 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07003808 }
3809
3810protected:
3811 sp<FakeWindowHandle> mWindow1;
3812 sp<FakeWindowHandle> mWindow2;
3813
3814 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05003815 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07003816 vec2 vals = windowInfo->transform.transform(point.x, point.y);
3817 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07003818 }
3819
3820 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
3821 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003822 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07003823 InputEvent* event = window->consume();
3824
3825 ASSERT_NE(nullptr, event) << name.c_str()
3826 << ": consumer should have returned non-NULL event.";
3827
3828 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
3829 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
3830 << " event, got " << inputEventTypeToString(event->getType()) << " event";
3831
3832 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003833 assertMotionAction(expectedAction, motionEvent.getAction());
chaviwaf87b3e2019-10-01 16:59:28 -07003834
3835 for (size_t i = 0; i < points.size(); i++) {
3836 float expectedX = points[i].x;
3837 float expectedY = points[i].y;
3838
3839 EXPECT_EQ(expectedX, motionEvent.getX(i))
3840 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
3841 << ", got " << motionEvent.getX(i);
3842 EXPECT_EQ(expectedY, motionEvent.getY(i))
3843 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
3844 << ", got " << motionEvent.getY(i);
3845 }
3846 }
chaviw9eaa22c2020-07-01 16:21:27 -07003847
3848 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
3849 std::vector<PointF> expectedPoints) {
3850 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
3851 ADISPLAY_ID_DEFAULT, touchedPoints);
3852 mDispatcher->notifyMotion(&motionArgs);
3853
3854 // Always consume from window1 since it's the window that has the InputReceiver
3855 consumeMotionEvent(mWindow1, action, expectedPoints);
3856 }
chaviwaf87b3e2019-10-01 16:59:28 -07003857};
3858
3859TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
3860 // Touch Window 1
3861 PointF touchedPoint = {10, 10};
3862 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003863 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003864
3865 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003866 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003867
3868 // Touch Window 2
3869 touchedPoint = {150, 150};
3870 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003871 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003872}
3873
chaviw9eaa22c2020-07-01 16:21:27 -07003874TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
3875 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07003876 mWindow2->setWindowScale(0.5f, 0.5f);
3877
3878 // Touch Window 1
3879 PointF touchedPoint = {10, 10};
3880 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003881 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003882 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003883 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003884
3885 // Touch Window 2
3886 touchedPoint = {150, 150};
3887 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003888 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
3889 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003890
chaviw9eaa22c2020-07-01 16:21:27 -07003891 // Update the transform so rotation is set
3892 mWindow2->setWindowTransform(0, -1, 1, 0);
3893 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
3894 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003895}
3896
chaviw9eaa22c2020-07-01 16:21:27 -07003897TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003898 mWindow2->setWindowScale(0.5f, 0.5f);
3899
3900 // Touch Window 1
3901 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3902 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003903 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003904
3905 // Touch Window 2
3906 int32_t actionPointerDown =
3907 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003908 touchedPoints.push_back(PointF{150, 150});
3909 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3910 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003911
chaviw9eaa22c2020-07-01 16:21:27 -07003912 // Release Window 2
3913 int32_t actionPointerUp =
3914 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3915 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3916 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003917
chaviw9eaa22c2020-07-01 16:21:27 -07003918 // Update the transform so rotation is set for Window 2
3919 mWindow2->setWindowTransform(0, -1, 1, 0);
3920 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3921 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003922}
3923
chaviw9eaa22c2020-07-01 16:21:27 -07003924TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003925 mWindow2->setWindowScale(0.5f, 0.5f);
3926
3927 // Touch Window 1
3928 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3929 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003930 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003931
3932 // Touch Window 2
3933 int32_t actionPointerDown =
3934 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003935 touchedPoints.push_back(PointF{150, 150});
3936 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003937
chaviw9eaa22c2020-07-01 16:21:27 -07003938 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003939
3940 // Move both windows
3941 touchedPoints = {{20, 20}, {175, 175}};
3942 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3943 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3944
chaviw9eaa22c2020-07-01 16:21:27 -07003945 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003946
chaviw9eaa22c2020-07-01 16:21:27 -07003947 // Release Window 2
3948 int32_t actionPointerUp =
3949 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3950 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3951 expectedPoints.pop_back();
3952
3953 // Touch Window 2
3954 mWindow2->setWindowTransform(0, -1, 1, 0);
3955 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3956 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
3957
3958 // Move both windows
3959 touchedPoints = {{20, 20}, {175, 175}};
3960 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3961 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3962
3963 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003964}
3965
3966TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
3967 mWindow1->setWindowScale(0.5f, 0.5f);
3968
3969 // Touch Window 1
3970 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3971 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003972 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003973
3974 // Touch Window 2
3975 int32_t actionPointerDown =
3976 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003977 touchedPoints.push_back(PointF{150, 150});
3978 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003979
chaviw9eaa22c2020-07-01 16:21:27 -07003980 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003981
3982 // Move both windows
3983 touchedPoints = {{20, 20}, {175, 175}};
3984 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3985 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3986
chaviw9eaa22c2020-07-01 16:21:27 -07003987 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003988}
3989
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003990class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
3991 virtual void SetUp() override {
3992 InputDispatcherTest::SetUp();
3993
Chris Yea209fde2020-07-22 13:54:51 -07003994 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003995 mApplication->setDispatchingTimeout(20ms);
3996 mWindow =
3997 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3998 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003999 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07004000 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004001 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4002 // window.
chaviw3277faf2021-05-19 16:45:23 -05004003 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004004
4005 // Set focused application.
4006 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
4007
4008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004009 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004010 mWindow->consumeFocusEvent(true);
4011 }
4012
4013 virtual void TearDown() override {
4014 InputDispatcherTest::TearDown();
4015 mWindow.clear();
4016 }
4017
4018protected:
Chris Yea209fde2020-07-22 13:54:51 -07004019 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004020 sp<FakeWindowHandle> mWindow;
4021 static constexpr PointF WINDOW_LOCATION = {20, 20};
4022
4023 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004025 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4026 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004028 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4029 WINDOW_LOCATION));
4030 }
4031};
4032
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004033// Send a tap and respond, which should not cause an ANR.
4034TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
4035 tapOnWindow();
4036 mWindow->consumeMotionDown();
4037 mWindow->consumeMotionUp();
4038 ASSERT_TRUE(mDispatcher->waitForIdle());
4039 mFakePolicy->assertNotifyAnrWasNotCalled();
4040}
4041
4042// Send a regular key and respond, which should not cause an ANR.
4043TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004045 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4046 ASSERT_TRUE(mDispatcher->waitForIdle());
4047 mFakePolicy->assertNotifyAnrWasNotCalled();
4048}
4049
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004050TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
4051 mWindow->setFocusable(false);
4052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4053 mWindow->consumeFocusEvent(false);
4054
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004055 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004056 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004057 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4058 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004060 // Key will not go to window because we have no focused window.
4061 // The 'no focused window' ANR timer should start instead.
4062
4063 // Now, the focused application goes away.
4064 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
4065 // The key should get dropped and there should be no ANR.
4066
4067 ASSERT_TRUE(mDispatcher->waitForIdle());
4068 mFakePolicy->assertNotifyAnrWasNotCalled();
4069}
4070
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004071// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004072// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
4073// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004074TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004076 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4077 WINDOW_LOCATION));
4078
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004079 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
4080 ASSERT_TRUE(sequenceNum);
4081 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004082 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004083
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004084 mWindow->finishEvent(*sequenceNum);
4085 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4086 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004087 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004088 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004089}
4090
4091// Send a key to the app and have the app not respond right away.
4092TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
4093 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004095 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
4096 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004097 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004098 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004099 ASSERT_TRUE(mDispatcher->waitForIdle());
4100}
4101
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004102// We have a focused application, but no focused window
4103TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004104 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004105 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4106 mWindow->consumeFocusEvent(false);
4107
4108 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004110 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4111 WINDOW_LOCATION));
4112 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
4113 mDispatcher->waitForIdle();
4114 mFakePolicy->assertNotifyAnrWasNotCalled();
4115
4116 // Once a focused event arrives, we get an ANR for this application
4117 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4118 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004119 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004120 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004121 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004122 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004123 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004124 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004125 ASSERT_TRUE(mDispatcher->waitForIdle());
4126}
4127
4128// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004129// Make sure that we don't notify policy twice about the same ANR.
4130TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004131 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004132 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4133 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004134
4135 // Once a focused event arrives, we get an ANR for this application
4136 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4137 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004138 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004139 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004140 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004141 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004142 const std::chrono::duration appTimeout =
4143 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004144 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004145
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004146 std::this_thread::sleep_for(appTimeout);
4147 // ANR should not be raised again. It is up to policy to do that if it desires.
4148 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004149
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004150 // If we now get a focused window, the ANR should stop, but the policy handles that via
4151 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004152 ASSERT_TRUE(mDispatcher->waitForIdle());
4153}
4154
4155// We have a focused application, but no focused window
4156TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004157 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004158 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4159 mWindow->consumeFocusEvent(false);
4160
4161 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004162 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004163 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004164 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4165 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004166
4167 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004168 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004169
4170 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004171 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004172 ASSERT_TRUE(mDispatcher->waitForIdle());
4173 mWindow->assertNoEvents();
4174}
4175
4176/**
4177 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
4178 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
4179 * If we process 1 of the events, but ANR on the second event with the same timestamp,
4180 * the ANR mechanism should still work.
4181 *
4182 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
4183 * DOWN event, while not responding on the second one.
4184 */
4185TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
4186 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
4187 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4188 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4189 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4190 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004191 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004192
4193 // Now send ACTION_UP, with identical timestamp
4194 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4195 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4196 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4197 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004198 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004199
4200 // We have now sent down and up. Let's consume first event and then ANR on the second.
4201 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4202 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004203 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004204}
4205
4206// If an app is not responding to a key event, gesture monitors should continue to receive
4207// new motion events
4208TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
4209 FakeMonitorReceiver monitor =
4210 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
4211 true /*isGestureMonitor*/);
4212
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4214 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004215 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004217
4218 // Stuck on the ACTION_UP
4219 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004220 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004221
4222 // New tap will go to the gesture monitor, but not to the window
4223 tapOnWindow();
4224 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4225 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4226
4227 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4228 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004229 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004230 mWindow->assertNoEvents();
4231 monitor.assertNoEvents();
4232}
4233
4234// If an app is not responding to a motion event, gesture monitors should continue to receive
4235// new motion events
4236TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
4237 FakeMonitorReceiver monitor =
4238 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
4239 true /*isGestureMonitor*/);
4240
4241 tapOnWindow();
4242 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4243 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4244
4245 mWindow->consumeMotionDown();
4246 // Stuck on the ACTION_UP
4247 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004248 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004249
4250 // New tap will go to the gesture monitor, but not to the window
4251 tapOnWindow();
4252 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4253 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
4254
4255 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4256 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004257 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004258 mWindow->assertNoEvents();
4259 monitor.assertNoEvents();
4260}
4261
4262// If a window is unresponsive, then you get anr. if the window later catches up and starts to
4263// process events, you don't get an anr. When the window later becomes unresponsive again, you
4264// get an ANR again.
4265// 1. tap -> block on ACTION_UP -> receive ANR
4266// 2. consume all pending events (= queue becomes healthy again)
4267// 3. tap again -> block on ACTION_UP again -> receive ANR second time
4268TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
4269 tapOnWindow();
4270
4271 mWindow->consumeMotionDown();
4272 // Block on ACTION_UP
4273 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004274 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004275 mWindow->consumeMotionUp(); // Now the connection should be healthy again
4276 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004277 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004278 mWindow->assertNoEvents();
4279
4280 tapOnWindow();
4281 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004282 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004283 mWindow->consumeMotionUp();
4284
4285 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004286 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004287 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004288 mWindow->assertNoEvents();
4289}
4290
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004291// If a connection remains unresponsive for a while, make sure policy is only notified once about
4292// it.
4293TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004295 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4296 WINDOW_LOCATION));
4297
4298 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004299 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004300 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004301 // 'notifyConnectionUnresponsive' should only be called once per connection
4302 mFakePolicy->assertNotifyAnrWasNotCalled();
4303 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004304 mWindow->consumeMotionDown();
4305 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4306 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4307 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004308 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004309 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004310 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004311}
4312
4313/**
4314 * If a window is processing a motion event, and then a key event comes in, the key event should
4315 * not to to the focused window until the motion is processed.
4316 *
4317 * Warning!!!
4318 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4319 * and the injection timeout that we specify when injecting the key.
4320 * We must have the injection timeout (10ms) be smaller than
4321 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4322 *
4323 * If that value changes, this test should also change.
4324 */
4325TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
4326 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4328
4329 tapOnWindow();
4330 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4331 ASSERT_TRUE(downSequenceNum);
4332 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4333 ASSERT_TRUE(upSequenceNum);
4334 // Don't finish the events yet, and send a key
4335 // Injection will "succeed" because we will eventually give up and send the key to the focused
4336 // window even if motions are still being processed. But because the injection timeout is short,
4337 // we will receive INJECTION_TIMED_OUT as the result.
4338
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004339 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004340 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004341 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4342 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004343 // Key will not be sent to the window, yet, because the window is still processing events
4344 // and the key remains pending, waiting for the touch events to be processed
4345 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4346 ASSERT_FALSE(keySequenceNum);
4347
4348 std::this_thread::sleep_for(500ms);
4349 // if we wait long enough though, dispatcher will give up, and still send the key
4350 // to the focused window, even though we have not yet finished the motion event
4351 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4352 mWindow->finishEvent(*downSequenceNum);
4353 mWindow->finishEvent(*upSequenceNum);
4354}
4355
4356/**
4357 * If a window is processing a motion event, and then a key event comes in, the key event should
4358 * not go to the focused window until the motion is processed.
4359 * If then a new motion comes in, then the pending key event should be going to the currently
4360 * focused window right away.
4361 */
4362TEST_F(InputDispatcherSingleWindowAnr,
4363 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
4364 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4365 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4366
4367 tapOnWindow();
4368 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4369 ASSERT_TRUE(downSequenceNum);
4370 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4371 ASSERT_TRUE(upSequenceNum);
4372 // Don't finish the events yet, and send a key
4373 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004375 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004376 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004377 // At this point, key is still pending, and should not be sent to the application yet.
4378 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4379 ASSERT_FALSE(keySequenceNum);
4380
4381 // Now tap down again. It should cause the pending key to go to the focused window right away.
4382 tapOnWindow();
4383 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
4384 // the other events yet. We can finish events in any order.
4385 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
4386 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
4387 mWindow->consumeMotionDown();
4388 mWindow->consumeMotionUp();
4389 mWindow->assertNoEvents();
4390}
4391
4392class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
4393 virtual void SetUp() override {
4394 InputDispatcherTest::SetUp();
4395
Chris Yea209fde2020-07-22 13:54:51 -07004396 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004397 mApplication->setDispatchingTimeout(10ms);
4398 mUnfocusedWindow =
4399 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
4400 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
4401 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4402 // window.
4403 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
chaviw3277faf2021-05-19 16:45:23 -05004404 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL |
4405 WindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
4406 WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004407
4408 mFocusedWindow =
4409 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004410 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004411 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05004412 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004413
4414 // Set focused application.
4415 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07004416 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004417
4418 // Expect one focus window exist in display.
4419 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004420 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004421 mFocusedWindow->consumeFocusEvent(true);
4422 }
4423
4424 virtual void TearDown() override {
4425 InputDispatcherTest::TearDown();
4426
4427 mUnfocusedWindow.clear();
4428 mFocusedWindow.clear();
4429 }
4430
4431protected:
Chris Yea209fde2020-07-22 13:54:51 -07004432 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004433 sp<FakeWindowHandle> mUnfocusedWindow;
4434 sp<FakeWindowHandle> mFocusedWindow;
4435 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
4436 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
4437 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
4438
4439 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
4440
4441 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
4442
4443private:
4444 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004446 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4447 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004449 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4450 location));
4451 }
4452};
4453
4454// If we have 2 windows that are both unresponsive, the one with the shortest timeout
4455// should be ANR'd first.
4456TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004458 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4459 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004460 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004461 mFocusedWindow->consumeMotionDown();
4462 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4463 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4464 // We consumed all events, so no ANR
4465 ASSERT_TRUE(mDispatcher->waitForIdle());
4466 mFakePolicy->assertNotifyAnrWasNotCalled();
4467
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004469 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4470 FOCUSED_WINDOW_LOCATION));
4471 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
4472 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004473
4474 const std::chrono::duration timeout =
4475 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004476 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004477 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
4478 // sequence to make it consistent
4479 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004480 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004481 mFocusedWindow->consumeMotionDown();
4482 // This cancel is generated because the connection was unresponsive
4483 mFocusedWindow->consumeMotionCancel();
4484 mFocusedWindow->assertNoEvents();
4485 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004486 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004487 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004488 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004489}
4490
4491// If we have 2 windows with identical timeouts that are both unresponsive,
4492// it doesn't matter which order they should have ANR.
4493// But we should receive ANR for both.
4494TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
4495 // Set the timeout for unfocused window to match the focused window
4496 mUnfocusedWindow->setDispatchingTimeout(10ms);
4497 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4498
4499 tapOnFocusedWindow();
4500 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004501 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
4502 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004503
4504 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004505 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
4506 mFocusedWindow->getToken() == anrConnectionToken2);
4507 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
4508 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004509
4510 ASSERT_TRUE(mDispatcher->waitForIdle());
4511 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004512
4513 mFocusedWindow->consumeMotionDown();
4514 mFocusedWindow->consumeMotionUp();
4515 mUnfocusedWindow->consumeMotionOutside();
4516
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004517 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
4518 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004519
4520 // Both applications should be marked as responsive, in any order
4521 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
4522 mFocusedWindow->getToken() == responsiveToken2);
4523 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
4524 mUnfocusedWindow->getToken() == responsiveToken2);
4525 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004526}
4527
4528// If a window is already not responding, the second tap on the same window should be ignored.
4529// We should also log an error to account for the dropped event (not tested here).
4530// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
4531TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
4532 tapOnFocusedWindow();
4533 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4534 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4535 // Receive the events, but don't respond
4536 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
4537 ASSERT_TRUE(downEventSequenceNum);
4538 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
4539 ASSERT_TRUE(upEventSequenceNum);
4540 const std::chrono::duration timeout =
4541 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004542 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004543
4544 // Tap once again
4545 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004546 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004547 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4548 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004549 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004550 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4551 FOCUSED_WINDOW_LOCATION));
4552 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
4553 // valid touch target
4554 mUnfocusedWindow->assertNoEvents();
4555
4556 // Consume the first tap
4557 mFocusedWindow->finishEvent(*downEventSequenceNum);
4558 mFocusedWindow->finishEvent(*upEventSequenceNum);
4559 ASSERT_TRUE(mDispatcher->waitForIdle());
4560 // The second tap did not go to the focused window
4561 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004562 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004563 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004564 mFakePolicy->assertNotifyAnrWasNotCalled();
4565}
4566
4567// If you tap outside of all windows, there will not be ANR
4568TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004569 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004570 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4571 LOCATION_OUTSIDE_ALL_WINDOWS));
4572 ASSERT_TRUE(mDispatcher->waitForIdle());
4573 mFakePolicy->assertNotifyAnrWasNotCalled();
4574}
4575
4576// Since the focused window is paused, tapping on it should not produce any events
4577TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
4578 mFocusedWindow->setPaused(true);
4579 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4580
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004581 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004582 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4583 FOCUSED_WINDOW_LOCATION));
4584
4585 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
4586 ASSERT_TRUE(mDispatcher->waitForIdle());
4587 // Should not ANR because the window is paused, and touches shouldn't go to it
4588 mFakePolicy->assertNotifyAnrWasNotCalled();
4589
4590 mFocusedWindow->assertNoEvents();
4591 mUnfocusedWindow->assertNoEvents();
4592}
4593
4594/**
4595 * If a window is processing a motion event, and then a key event comes in, the key event should
4596 * not to to the focused window until the motion is processed.
4597 * If a different window becomes focused at this time, the key should go to that window instead.
4598 *
4599 * Warning!!!
4600 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4601 * and the injection timeout that we specify when injecting the key.
4602 * We must have the injection timeout (10ms) be smaller than
4603 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4604 *
4605 * If that value changes, this test should also change.
4606 */
4607TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
4608 // Set a long ANR timeout to prevent it from triggering
4609 mFocusedWindow->setDispatchingTimeout(2s);
4610 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4611
4612 tapOnUnfocusedWindow();
4613 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
4614 ASSERT_TRUE(downSequenceNum);
4615 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
4616 ASSERT_TRUE(upSequenceNum);
4617 // Don't finish the events yet, and send a key
4618 // Injection will succeed because we will eventually give up and send the key to the focused
4619 // window even if motions are still being processed.
4620
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004621 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004622 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004623 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
4624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004625 // Key will not be sent to the window, yet, because the window is still processing events
4626 // and the key remains pending, waiting for the touch events to be processed
4627 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
4628 ASSERT_FALSE(keySequenceNum);
4629
4630 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07004631 mFocusedWindow->setFocusable(false);
4632 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004633 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004634 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004635
4636 // Focus events should precede the key events
4637 mUnfocusedWindow->consumeFocusEvent(true);
4638 mFocusedWindow->consumeFocusEvent(false);
4639
4640 // Finish the tap events, which should unblock dispatcher
4641 mUnfocusedWindow->finishEvent(*downSequenceNum);
4642 mUnfocusedWindow->finishEvent(*upSequenceNum);
4643
4644 // Now that all queues are cleared and no backlog in the connections, the key event
4645 // can finally go to the newly focused "mUnfocusedWindow".
4646 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4647 mFocusedWindow->assertNoEvents();
4648 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004649 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004650}
4651
4652// When the touch stream is split across 2 windows, and one of them does not respond,
4653// then ANR should be raised and the touch should be canceled for the unresponsive window.
4654// The other window should not be affected by that.
4655TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
4656 // Touch Window 1
4657 NotifyMotionArgs motionArgs =
4658 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4659 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
4660 mDispatcher->notifyMotion(&motionArgs);
4661 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4662 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4663
4664 // Touch Window 2
4665 int32_t actionPointerDown =
4666 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4667
4668 motionArgs =
4669 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4670 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
4671 mDispatcher->notifyMotion(&motionArgs);
4672
4673 const std::chrono::duration timeout =
4674 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004675 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004676
4677 mUnfocusedWindow->consumeMotionDown();
4678 mFocusedWindow->consumeMotionDown();
4679 // Focused window may or may not receive ACTION_MOVE
4680 // But it should definitely receive ACTION_CANCEL due to the ANR
4681 InputEvent* event;
4682 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
4683 ASSERT_TRUE(moveOrCancelSequenceNum);
4684 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
4685 ASSERT_NE(nullptr, event);
4686 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
4687 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
4688 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
4689 mFocusedWindow->consumeMotionCancel();
4690 } else {
4691 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
4692 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004693 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004694 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004695
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004696 mUnfocusedWindow->assertNoEvents();
4697 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004698 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004699}
4700
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004701/**
4702 * If we have no focused window, and a key comes in, we start the ANR timer.
4703 * The focused application should add a focused window before the timer runs out to prevent ANR.
4704 *
4705 * If the user touches another application during this time, the key should be dropped.
4706 * Next, if a new focused window comes in, without toggling the focused application,
4707 * then no ANR should occur.
4708 *
4709 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
4710 * but in some cases the policy may not update the focused application.
4711 */
4712TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
4713 std::shared_ptr<FakeApplicationHandle> focusedApplication =
4714 std::make_shared<FakeApplicationHandle>();
4715 focusedApplication->setDispatchingTimeout(60ms);
4716 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
4717 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
4718 mFocusedWindow->setFocusable(false);
4719
4720 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4721 mFocusedWindow->consumeFocusEvent(false);
4722
4723 // Send a key. The ANR timer should start because there is no focused window.
4724 // 'focusedApplication' will get blamed if this timer completes.
4725 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004726 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004727 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004728 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4729 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004731
4732 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
4733 // then the injected touches won't cause the focused event to get dropped.
4734 // The dispatcher only checks for whether the queue should be pruned upon queueing.
4735 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
4736 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
4737 // For this test, it means that the key would get delivered to the window once it becomes
4738 // focused.
4739 std::this_thread::sleep_for(10ms);
4740
4741 // Touch unfocused window. This should force the pending key to get dropped.
4742 NotifyMotionArgs motionArgs =
4743 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4744 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
4745 mDispatcher->notifyMotion(&motionArgs);
4746
4747 // We do not consume the motion right away, because that would require dispatcher to first
4748 // process (== drop) the key event, and by that time, ANR will be raised.
4749 // Set the focused window first.
4750 mFocusedWindow->setFocusable(true);
4751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4752 setFocusedWindow(mFocusedWindow);
4753 mFocusedWindow->consumeFocusEvent(true);
4754 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
4755 // to another application. This could be a bug / behaviour in the policy.
4756
4757 mUnfocusedWindow->consumeMotionDown();
4758
4759 ASSERT_TRUE(mDispatcher->waitForIdle());
4760 // Should not ANR because we actually have a focused window. It was just added too slowly.
4761 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
4762}
4763
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004764// These tests ensure we cannot send touch events to a window that's positioned behind a window
4765// that has feature NO_INPUT_CHANNEL.
4766// Layout:
4767// Top (closest to user)
4768// mNoInputWindow (above all windows)
4769// mBottomWindow
4770// Bottom (furthest from user)
4771class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
4772 virtual void SetUp() override {
4773 InputDispatcherTest::SetUp();
4774
4775 mApplication = std::make_shared<FakeApplicationHandle>();
4776 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4777 "Window without input channel", ADISPLAY_ID_DEFAULT,
4778 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
4779
chaviw3277faf2021-05-19 16:45:23 -05004780 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004781 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4782 // It's perfectly valid for this window to not have an associated input channel
4783
4784 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
4785 ADISPLAY_ID_DEFAULT);
4786 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
4787
4788 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4789 }
4790
4791protected:
4792 std::shared_ptr<FakeApplicationHandle> mApplication;
4793 sp<FakeWindowHandle> mNoInputWindow;
4794 sp<FakeWindowHandle> mBottomWindow;
4795};
4796
4797TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
4798 PointF touchedPoint = {10, 10};
4799
4800 NotifyMotionArgs motionArgs =
4801 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4802 ADISPLAY_ID_DEFAULT, {touchedPoint});
4803 mDispatcher->notifyMotion(&motionArgs);
4804
4805 mNoInputWindow->assertNoEvents();
4806 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
4807 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
4808 // and therefore should prevent mBottomWindow from receiving touches
4809 mBottomWindow->assertNoEvents();
4810}
4811
4812/**
4813 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
4814 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
4815 */
4816TEST_F(InputDispatcherMultiWindowOcclusionTests,
4817 NoInputChannelFeature_DropsTouchesWithValidChannel) {
4818 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4819 "Window with input channel and NO_INPUT_CHANNEL",
4820 ADISPLAY_ID_DEFAULT);
4821
chaviw3277faf2021-05-19 16:45:23 -05004822 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004823 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4824 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4825
4826 PointF touchedPoint = {10, 10};
4827
4828 NotifyMotionArgs motionArgs =
4829 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4830 ADISPLAY_ID_DEFAULT, {touchedPoint});
4831 mDispatcher->notifyMotion(&motionArgs);
4832
4833 mNoInputWindow->assertNoEvents();
4834 mBottomWindow->assertNoEvents();
4835}
4836
Vishnu Nair958da932020-08-21 17:12:37 -07004837class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
4838protected:
4839 std::shared_ptr<FakeApplicationHandle> mApp;
4840 sp<FakeWindowHandle> mWindow;
4841 sp<FakeWindowHandle> mMirror;
4842
4843 virtual void SetUp() override {
4844 InputDispatcherTest::SetUp();
4845 mApp = std::make_shared<FakeApplicationHandle>();
4846 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4847 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
4848 mWindow->getToken());
4849 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4850 mWindow->setFocusable(true);
4851 mMirror->setFocusable(true);
4852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4853 }
4854};
4855
4856TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
4857 // Request focus on a mirrored window
4858 setFocusedWindow(mMirror);
4859
4860 // window gets focused
4861 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4863 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004864 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4865}
4866
4867// A focused & mirrored window remains focused only if the window and its mirror are both
4868// focusable.
4869TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
4870 setFocusedWindow(mMirror);
4871
4872 // window gets focused
4873 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4875 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004876 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4878 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004879 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4880
4881 mMirror->setFocusable(false);
4882 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4883
4884 // window loses focus since one of the windows associated with the token in not focusable
4885 mWindow->consumeFocusEvent(false);
4886
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004887 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4888 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004889 mWindow->assertNoEvents();
4890}
4891
4892// A focused & mirrored window remains focused until the window and its mirror both become
4893// invisible.
4894TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
4895 setFocusedWindow(mMirror);
4896
4897 // window gets focused
4898 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4900 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004901 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4903 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004904 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4905
4906 mMirror->setVisible(false);
4907 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4908
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4910 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004911 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4913 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004914 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4915
4916 mWindow->setVisible(false);
4917 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4918
4919 // window loses focus only after all windows associated with the token become invisible.
4920 mWindow->consumeFocusEvent(false);
4921
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004922 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4923 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004924 mWindow->assertNoEvents();
4925}
4926
4927// A focused & mirrored window remains focused until both windows are removed.
4928TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
4929 setFocusedWindow(mMirror);
4930
4931 // window gets focused
4932 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4934 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004935 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4937 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004938 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4939
4940 // single window is removed but the window token remains focused
4941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
4942
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4944 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004945 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4947 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004948 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4949
4950 // Both windows are removed
4951 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4952 mWindow->consumeFocusEvent(false);
4953
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004954 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4955 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004956 mWindow->assertNoEvents();
4957}
4958
4959// Focus request can be pending until one window becomes visible.
4960TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
4961 // Request focus on an invisible mirror.
4962 mWindow->setVisible(false);
4963 mMirror->setVisible(false);
4964 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4965 setFocusedWindow(mMirror);
4966
4967 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07004969 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004970 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07004971
4972 mMirror->setVisible(true);
4973 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4974
4975 // window gets focused
4976 mWindow->consumeFocusEvent(true);
4977 // window gets the pending key event
4978 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4979}
Prabir Pradhan99987712020-11-10 18:43:05 -08004980
4981class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
4982protected:
4983 std::shared_ptr<FakeApplicationHandle> mApp;
4984 sp<FakeWindowHandle> mWindow;
4985 sp<FakeWindowHandle> mSecondWindow;
4986
4987 void SetUp() override {
4988 InputDispatcherTest::SetUp();
4989 mApp = std::make_shared<FakeApplicationHandle>();
4990 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4991 mWindow->setFocusable(true);
4992 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
4993 mSecondWindow->setFocusable(true);
4994
4995 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
4997
4998 setFocusedWindow(mWindow);
4999 mWindow->consumeFocusEvent(true);
5000 }
5001
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005002 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
5003 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005004 mDispatcher->notifyPointerCaptureChanged(&args);
5005 }
5006
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005007 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
5008 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08005009 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005010 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
5011 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005012 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005013 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08005014 }
5015};
5016
5017TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
5018 // Ensure that capture cannot be obtained for unfocused windows.
5019 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
5020 mFakePolicy->assertSetPointerCaptureNotCalled();
5021 mSecondWindow->assertNoEvents();
5022
5023 // Ensure that capture can be enabled from the focus window.
5024 requestAndVerifyPointerCapture(mWindow, true);
5025
5026 // Ensure that capture cannot be disabled from a window that does not have capture.
5027 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
5028 mFakePolicy->assertSetPointerCaptureNotCalled();
5029
5030 // Ensure that capture can be disabled from the window with capture.
5031 requestAndVerifyPointerCapture(mWindow, false);
5032}
5033
5034TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005035 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005036
5037 setFocusedWindow(mSecondWindow);
5038
5039 // Ensure that the capture disabled event was sent first.
5040 mWindow->consumeCaptureEvent(false);
5041 mWindow->consumeFocusEvent(false);
5042 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005043 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005044
5045 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005046 notifyPointerCaptureChanged({});
5047 notifyPointerCaptureChanged(request);
5048 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08005049 mWindow->assertNoEvents();
5050 mSecondWindow->assertNoEvents();
5051 mFakePolicy->assertSetPointerCaptureNotCalled();
5052}
5053
5054TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005055 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005056
5057 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005058 notifyPointerCaptureChanged({});
5059 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005060
5061 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005062 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005063 mWindow->consumeCaptureEvent(false);
5064 mWindow->assertNoEvents();
5065}
5066
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005067TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
5068 requestAndVerifyPointerCapture(mWindow, true);
5069
5070 // The first window loses focus.
5071 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005072 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005073 mWindow->consumeCaptureEvent(false);
5074
5075 // Request Pointer Capture from the second window before the notification from InputReader
5076 // arrives.
5077 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005078 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005079
5080 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005081 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005082
5083 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005084 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005085
5086 mSecondWindow->consumeFocusEvent(true);
5087 mSecondWindow->consumeCaptureEvent(true);
5088}
5089
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005090TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
5091 // App repeatedly enables and disables capture.
5092 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5093 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5094 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
5095 mFakePolicy->assertSetPointerCaptureCalled(false);
5096 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5097 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5098
5099 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
5100 // first request is now stale, this should do nothing.
5101 notifyPointerCaptureChanged(firstRequest);
5102 mWindow->assertNoEvents();
5103
5104 // InputReader notifies that the second request was enabled.
5105 notifyPointerCaptureChanged(secondRequest);
5106 mWindow->consumeCaptureEvent(true);
5107}
5108
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005109class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
5110protected:
5111 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00005112
5113 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
5114 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
5115
5116 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
5117 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5118
5119 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
5120 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
5121 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5122 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
5123 MAXIMUM_OBSCURING_OPACITY);
5124
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005125 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005126 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005127 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005128
5129 sp<FakeWindowHandle> mTouchWindow;
5130
5131 virtual void SetUp() override {
5132 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005133 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005134 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
5135 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
5136 }
5137
5138 virtual void TearDown() override {
5139 InputDispatcherTest::TearDown();
5140 mTouchWindow.clear();
5141 }
5142
chaviw3277faf2021-05-19 16:45:23 -05005143 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
5144 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005145 sp<FakeWindowHandle> window = getWindow(uid, name);
chaviw3277faf2021-05-19 16:45:23 -05005146 window->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005147 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005148 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005149 return window;
5150 }
5151
5152 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
5153 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
5154 sp<FakeWindowHandle> window =
5155 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
5156 // Generate an arbitrary PID based on the UID
5157 window->setOwnerInfo(1777 + (uid % 10000), uid);
5158 return window;
5159 }
5160
5161 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
5162 NotifyMotionArgs args =
5163 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5164 ADISPLAY_ID_DEFAULT, points);
5165 mDispatcher->notifyMotion(&args);
5166 }
5167};
5168
5169TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005170 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005171 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005173
5174 touch();
5175
5176 mTouchWindow->assertNoEvents();
5177}
5178
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005179TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00005180 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
5181 const sp<FakeWindowHandle>& w =
5182 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
5183 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5184
5185 touch();
5186
5187 mTouchWindow->assertNoEvents();
5188}
5189
5190TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005191 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
5192 const sp<FakeWindowHandle>& w =
5193 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5195
5196 touch();
5197
5198 w->assertNoEvents();
5199}
5200
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005201TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005202 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
5203 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005204
5205 touch();
5206
5207 mTouchWindow->consumeAnyMotionDown();
5208}
5209
5210TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005211 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005212 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005213 w->setFrame(Rect(0, 0, 50, 50));
5214 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005215
5216 touch({PointF{100, 100}});
5217
5218 mTouchWindow->consumeAnyMotionDown();
5219}
5220
5221TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005222 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005223 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005224 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5225
5226 touch();
5227
5228 mTouchWindow->consumeAnyMotionDown();
5229}
5230
5231TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
5232 const sp<FakeWindowHandle>& w =
5233 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5234 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005235
5236 touch();
5237
5238 mTouchWindow->consumeAnyMotionDown();
5239}
5240
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005241TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
5242 const sp<FakeWindowHandle>& w =
5243 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5244 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5245
5246 touch();
5247
5248 w->assertNoEvents();
5249}
5250
5251/**
5252 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
5253 * inside) while letting them pass-through. Note that even though touch passes through the occluding
5254 * window, the occluding window will still receive ACTION_OUTSIDE event.
5255 */
5256TEST_F(InputDispatcherUntrustedTouchesTest,
5257 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
5258 const sp<FakeWindowHandle>& w =
5259 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05005260 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005261 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5262
5263 touch();
5264
5265 w->consumeMotionOutside();
5266}
5267
5268TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
5269 const sp<FakeWindowHandle>& w =
5270 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05005271 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005272 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5273
5274 touch();
5275
5276 InputEvent* event = w->consume();
5277 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
5278 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5279 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getX());
5280 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getY());
5281}
5282
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005283TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005284 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005285 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5286 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5288
5289 touch();
5290
5291 mTouchWindow->consumeAnyMotionDown();
5292}
5293
5294TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
5295 const sp<FakeWindowHandle>& w =
5296 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5297 MAXIMUM_OBSCURING_OPACITY);
5298 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005299
5300 touch();
5301
5302 mTouchWindow->consumeAnyMotionDown();
5303}
5304
5305TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005306 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005307 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5308 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005309 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5310
5311 touch();
5312
5313 mTouchWindow->assertNoEvents();
5314}
5315
5316TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
5317 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
5318 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005319 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5320 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005321 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005322 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5323 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005324 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5325
5326 touch();
5327
5328 mTouchWindow->assertNoEvents();
5329}
5330
5331TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
5332 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
5333 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005334 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5335 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005336 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005337 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5338 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005339 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5340
5341 touch();
5342
5343 mTouchWindow->consumeAnyMotionDown();
5344}
5345
5346TEST_F(InputDispatcherUntrustedTouchesTest,
5347 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
5348 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005349 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5350 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005351 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005352 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5353 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005354 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5355
5356 touch();
5357
5358 mTouchWindow->consumeAnyMotionDown();
5359}
5360
5361TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
5362 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005363 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5364 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005365 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005366 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5367 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005368 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005369
5370 touch();
5371
5372 mTouchWindow->assertNoEvents();
5373}
5374
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005375TEST_F(InputDispatcherUntrustedTouchesTest,
5376 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
5377 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005378 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5379 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005380 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005381 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5382 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005383 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5384
5385 touch();
5386
5387 mTouchWindow->assertNoEvents();
5388}
5389
5390TEST_F(InputDispatcherUntrustedTouchesTest,
5391 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
5392 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005393 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5394 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005395 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005396 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5397 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5399
5400 touch();
5401
5402 mTouchWindow->consumeAnyMotionDown();
5403}
5404
5405TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
5406 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005407 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5408 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005409 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5410
5411 touch();
5412
5413 mTouchWindow->consumeAnyMotionDown();
5414}
5415
5416TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
5417 const sp<FakeWindowHandle>& w =
5418 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
5419 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5420
5421 touch();
5422
5423 mTouchWindow->consumeAnyMotionDown();
5424}
5425
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005426TEST_F(InputDispatcherUntrustedTouchesTest,
5427 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
5428 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5429 const sp<FakeWindowHandle>& w =
5430 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
5431 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5432
5433 touch();
5434
5435 mTouchWindow->assertNoEvents();
5436}
5437
5438TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
5439 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5440 const sp<FakeWindowHandle>& w =
5441 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
5442 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5443
5444 touch();
5445
5446 mTouchWindow->consumeAnyMotionDown();
5447}
5448
5449TEST_F(InputDispatcherUntrustedTouchesTest,
5450 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
5451 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
5452 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005453 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5454 OPACITY_ABOVE_THRESHOLD);
5455 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5456
5457 touch();
5458
5459 mTouchWindow->consumeAnyMotionDown();
5460}
5461
5462TEST_F(InputDispatcherUntrustedTouchesTest,
5463 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
5464 const sp<FakeWindowHandle>& w1 =
5465 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5466 OPACITY_BELOW_THRESHOLD);
5467 const sp<FakeWindowHandle>& w2 =
5468 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5469 OPACITY_BELOW_THRESHOLD);
5470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5471
5472 touch();
5473
5474 mTouchWindow->assertNoEvents();
5475}
5476
5477/**
5478 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
5479 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
5480 * (which alone would result in allowing touches) does not affect the blocking behavior.
5481 */
5482TEST_F(InputDispatcherUntrustedTouchesTest,
5483 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
5484 const sp<FakeWindowHandle>& wB =
5485 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5486 OPACITY_BELOW_THRESHOLD);
5487 const sp<FakeWindowHandle>& wC =
5488 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5489 OPACITY_BELOW_THRESHOLD);
5490 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5491
5492 touch();
5493
5494 mTouchWindow->assertNoEvents();
5495}
5496
5497/**
5498 * This test is testing that a window from a different UID but with same application token doesn't
5499 * block the touch. Apps can share the application token for close UI collaboration for example.
5500 */
5501TEST_F(InputDispatcherUntrustedTouchesTest,
5502 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
5503 const sp<FakeWindowHandle>& w =
5504 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5505 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005506 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5507
5508 touch();
5509
5510 mTouchWindow->consumeAnyMotionDown();
5511}
5512
arthurhungb89ccb02020-12-30 16:19:01 +08005513class InputDispatcherDragTests : public InputDispatcherTest {
5514protected:
5515 std::shared_ptr<FakeApplicationHandle> mApp;
5516 sp<FakeWindowHandle> mWindow;
5517 sp<FakeWindowHandle> mSecondWindow;
5518 sp<FakeWindowHandle> mDragWindow;
5519
5520 void SetUp() override {
5521 InputDispatcherTest::SetUp();
5522 mApp = std::make_shared<FakeApplicationHandle>();
5523 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5524 mWindow->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05005525 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005526
5527 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5528 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
chaviw3277faf2021-05-19 16:45:23 -05005529 mSecondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005530
5531 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5532 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5533 }
5534
5535 // Start performing drag, we will create a drag window and transfer touch to it.
5536 void performDrag() {
5537 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5538 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5539 {50, 50}))
5540 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5541
5542 // Window should receive motion event.
5543 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5544
5545 // The drag window covers the entire display
5546 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5547 mDispatcher->setInputWindows(
5548 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5549
5550 // Transfer touch focus to the drag window
5551 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5552 true /* isDragDrop */);
5553 mWindow->consumeMotionCancel();
5554 mDragWindow->consumeMotionDown();
5555 }
arthurhung6d4bed92021-03-17 11:59:33 +08005556
5557 // Start performing drag, we will create a drag window and transfer touch to it.
5558 void performStylusDrag() {
5559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5560 injectMotionEvent(mDispatcher,
5561 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
5562 AINPUT_SOURCE_STYLUS)
5563 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5564 .pointer(PointerBuilder(0,
5565 AMOTION_EVENT_TOOL_TYPE_STYLUS)
5566 .x(50)
5567 .y(50))
5568 .build()));
5569 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5570
5571 // The drag window covers the entire display
5572 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5573 mDispatcher->setInputWindows(
5574 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5575
5576 // Transfer touch focus to the drag window
5577 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5578 true /* isDragDrop */);
5579 mWindow->consumeMotionCancel();
5580 mDragWindow->consumeMotionDown();
5581 }
arthurhungb89ccb02020-12-30 16:19:01 +08005582};
5583
5584TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
5585 performDrag();
5586
5587 // Move on window.
5588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5589 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5590 ADISPLAY_ID_DEFAULT, {50, 50}))
5591 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5592 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5593 mWindow->consumeDragEvent(false, 50, 50);
5594 mSecondWindow->assertNoEvents();
5595
5596 // Move to another window.
5597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5598 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5599 ADISPLAY_ID_DEFAULT, {150, 50}))
5600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5601 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5602 mWindow->consumeDragEvent(true, 150, 50);
5603 mSecondWindow->consumeDragEvent(false, 50, 50);
5604
5605 // Move back to original window.
5606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5607 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5608 ADISPLAY_ID_DEFAULT, {50, 50}))
5609 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5610 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5611 mWindow->consumeDragEvent(false, 50, 50);
5612 mSecondWindow->consumeDragEvent(true, -50, 50);
5613
5614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5615 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
5616 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5617 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5618 mWindow->assertNoEvents();
5619 mSecondWindow->assertNoEvents();
5620}
5621
arthurhungf452d0b2021-01-06 00:19:52 +08005622TEST_F(InputDispatcherDragTests, DragAndDrop) {
5623 performDrag();
5624
5625 // Move on window.
5626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5627 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5628 ADISPLAY_ID_DEFAULT, {50, 50}))
5629 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5630 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5631 mWindow->consumeDragEvent(false, 50, 50);
5632 mSecondWindow->assertNoEvents();
5633
5634 // Move to another window.
5635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5636 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5637 ADISPLAY_ID_DEFAULT, {150, 50}))
5638 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5639 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5640 mWindow->consumeDragEvent(true, 150, 50);
5641 mSecondWindow->consumeDragEvent(false, 50, 50);
5642
5643 // drop to another window.
5644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5645 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5646 {150, 50}))
5647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5648 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5649 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5650 mWindow->assertNoEvents();
5651 mSecondWindow->assertNoEvents();
5652}
5653
arthurhung6d4bed92021-03-17 11:59:33 +08005654TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
5655 performStylusDrag();
5656
5657 // Move on window and keep button pressed.
5658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5659 injectMotionEvent(mDispatcher,
5660 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5661 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5662 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5663 .x(50)
5664 .y(50))
5665 .build()))
5666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5667 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5668 mWindow->consumeDragEvent(false, 50, 50);
5669 mSecondWindow->assertNoEvents();
5670
5671 // Move to another window and release button, expect to drop item.
5672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5673 injectMotionEvent(mDispatcher,
5674 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5675 .buttonState(0)
5676 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5677 .x(150)
5678 .y(50))
5679 .build()))
5680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5681 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5682 mWindow->assertNoEvents();
5683 mSecondWindow->assertNoEvents();
5684 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5685
5686 // nothing to the window.
5687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5688 injectMotionEvent(mDispatcher,
5689 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
5690 .buttonState(0)
5691 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5692 .x(150)
5693 .y(50))
5694 .build()))
5695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5696 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5697 mWindow->assertNoEvents();
5698 mSecondWindow->assertNoEvents();
5699}
5700
Arthur Hung6d0571e2021-04-09 20:18:16 +08005701TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
5702 performDrag();
5703
5704 // Set second window invisible.
5705 mSecondWindow->setVisible(false);
5706 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5707
5708 // Move on window.
5709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5710 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5711 ADISPLAY_ID_DEFAULT, {50, 50}))
5712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5713 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5714 mWindow->consumeDragEvent(false, 50, 50);
5715 mSecondWindow->assertNoEvents();
5716
5717 // Move to another window.
5718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5719 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5720 ADISPLAY_ID_DEFAULT, {150, 50}))
5721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5722 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5723 mWindow->consumeDragEvent(true, 150, 50);
5724 mSecondWindow->assertNoEvents();
5725
5726 // drop to another window.
5727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5728 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5729 {150, 50}))
5730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5731 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5732 mFakePolicy->assertDropTargetEquals(nullptr);
5733 mWindow->assertNoEvents();
5734 mSecondWindow->assertNoEvents();
5735}
5736
Garfield Tane84e6f92019-08-29 17:28:41 -07005737} // namespace android::inputdispatcher