blob: 0c2f11bde52e1933273cc95622380b73310cc35e [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Garfield Tan1c7bc862020-01-28 13:24:04 -080019#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070020#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070021#include <binder/Binder.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080022#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100023#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080024#include <linux/input.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100025
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080029#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050032using android::gui::FocusRequest;
33using android::gui::TouchOcclusionMode;
34using android::gui::WindowInfo;
35using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080036using android::os::InputEventInjectionResult;
37using android::os::InputEventInjectionSync;
Michael Wright44753b12020-07-08 13:48:11 +010038using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080039
Garfield Tane84e6f92019-08-29 17:28:41 -070040namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080041
42// An arbitrary time value.
43static const nsecs_t ARBITRARY_TIME = 1234;
44
45// An arbitrary device id.
46static const int32_t DEVICE_ID = 1;
47
Jeff Brownf086ddb2014-02-11 14:28:48 -080048// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000049static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
50static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052// An arbitrary injector pid / uid pair that has permission to inject events.
53static const int32_t INJECTOR_PID = 999;
54static const int32_t INJECTOR_UID = 1001;
55
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000056// An arbitrary pid of the gesture monitor window
57static constexpr int32_t MONITOR_PID = 2001;
58
chaviwd1c23182019-12-20 18:44:56 -080059struct PointF {
60 float x;
61 float y;
62};
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
Gang Wang342c9272020-01-13 13:15:04 -050064/**
65 * Return a DOWN key event with KEYCODE_A.
66 */
67static KeyEvent getTestKeyEvent() {
68 KeyEvent event;
69
Garfield Tanfbe732e2020-01-24 11:26:14 -080070 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
71 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
72 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050073 return event;
74}
75
Michael Wrightd02c5b62014-02-10 15:10:22 -080076// --- FakeInputDispatcherPolicy ---
77
78class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
79 InputDispatcherConfiguration mConfig;
80
81protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100082 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080083
84public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100085 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080086
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080087 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080088 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_KEY, args.eventTime, args.action,
89 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080090 }
91
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080092 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args) {
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -080093 assertFilterInputEventWasCalled(AINPUT_EVENT_TYPE_MOTION, args.eventTime, args.action,
94 args.displayId);
Jackal Guof9696682018-10-05 12:23:23 +080095 }
96
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -070097 void assertFilterInputEventWasNotCalled() {
98 std::scoped_lock lock(mLock);
99 ASSERT_EQ(nullptr, mFilteredEvent);
100 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800101
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800102 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700103 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800104 ASSERT_TRUE(mConfigurationChangedTime)
105 << "Timed out waiting for configuration changed call";
106 ASSERT_EQ(*mConfigurationChangedTime, when);
107 mConfigurationChangedTime = std::nullopt;
108 }
109
110 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700111 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800112 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800113 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800114 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
115 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
116 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
117 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
118 mLastNotifySwitch = std::nullopt;
119 }
120
chaviwfd6d3512019-03-25 13:23:49 -0700121 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700122 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800123 ASSERT_EQ(touchedToken, mOnPointerDownToken);
124 mOnPointerDownToken.clear();
125 }
126
127 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700128 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800129 ASSERT_TRUE(mOnPointerDownToken == nullptr)
130 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700131 }
132
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700133 // This function must be called soon after the expected ANR timer starts,
134 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500135 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700136 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500137 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
138 std::shared_ptr<InputApplicationHandle> application;
139 { // acquire lock
140 std::unique_lock lock(mLock);
141 android::base::ScopedLockAssertion assumeLocked(mLock);
142 ASSERT_NO_FATAL_FAILURE(
143 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
144 } // release lock
145 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700146 }
147
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000148 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
149 const sp<IBinder>& expectedConnectionToken) {
150 sp<IBinder> connectionToken = getUnresponsiveWindowToken(timeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500151 ASSERT_EQ(expectedConnectionToken, connectionToken);
152 }
153
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000154 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
155 sp<IBinder> connectionToken = getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500156 ASSERT_EQ(expectedConnectionToken, connectionToken);
157 }
158
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000159 void assertNotifyMonitorUnresponsiveWasCalled(std::chrono::nanoseconds timeout) {
160 int32_t pid = getUnresponsiveMonitorPid(timeout);
161 ASSERT_EQ(MONITOR_PID, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500162 }
163
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000164 void assertNotifyMonitorResponsiveWasCalled() {
165 int32_t pid = getResponsiveMonitorPid();
166 ASSERT_EQ(MONITOR_PID, pid);
167 }
168
169 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500170 std::unique_lock lock(mLock);
171 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000172 return getAnrTokenLockedInterruptible(timeout, mAnrWindowTokens, lock);
173 }
174
175 sp<IBinder> getResponsiveWindowToken() {
176 std::unique_lock lock(mLock);
177 android::base::ScopedLockAssertion assumeLocked(mLock);
178 return getAnrTokenLockedInterruptible(0s, mResponsiveWindowTokens, lock);
179 }
180
181 int32_t getUnresponsiveMonitorPid(std::chrono::nanoseconds timeout) {
182 std::unique_lock lock(mLock);
183 android::base::ScopedLockAssertion assumeLocked(mLock);
184 return getAnrTokenLockedInterruptible(timeout, mAnrMonitorPids, lock);
185 }
186
187 int32_t getResponsiveMonitorPid() {
188 std::unique_lock lock(mLock);
189 android::base::ScopedLockAssertion assumeLocked(mLock);
190 return getAnrTokenLockedInterruptible(0s, mResponsiveMonitorPids, lock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500191 }
192
193 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
194 // for a specific container to become non-empty. When the container is non-empty, return the
195 // first entry from the container and erase it.
196 template <class T>
197 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
198 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
199 const std::chrono::time_point start = std::chrono::steady_clock::now();
200 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700201
202 // If there is an ANR, Dispatcher won't be idle because there are still events
203 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
204 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500205 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
206 // to provide it some time to act. 100ms seems reasonable.
207 mNotifyAnr.wait_for(lock, timeToWait,
208 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700209 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500210 if (storage.empty()) {
211 ADD_FAILURE() << "Did not receive the ANR callback";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000212 return {};
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700213 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700214 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
215 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700216 if (std::chrono::abs(timeout - waited) > 100ms) {
217 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
218 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
219 << "ms, but waited "
220 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
221 << "ms instead";
222 }
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500223 T token = storage.front();
224 storage.pop();
225 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700226 }
227
228 void assertNotifyAnrWasNotCalled() {
229 std::scoped_lock lock(mLock);
230 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000231 ASSERT_TRUE(mAnrWindowTokens.empty());
232 ASSERT_TRUE(mAnrMonitorPids.empty());
233 ASSERT_TRUE(mResponsiveWindowTokens.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500234 << "ANR was not called, but please also consume the 'connection is responsive' "
235 "signal";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000236 ASSERT_TRUE(mResponsiveMonitorPids.empty())
237 << "Monitor ANR was not called, but please also consume the 'monitor is responsive'"
238 " signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700239 }
240
Garfield Tan1c7bc862020-01-28 13:24:04 -0800241 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
242 mConfig.keyRepeatTimeout = timeout;
243 mConfig.keyRepeatDelay = delay;
244 }
245
Prabir Pradhan99987712020-11-10 18:43:05 -0800246 void waitForSetPointerCapture(bool enabled) {
247 std::unique_lock lock(mLock);
248 base::ScopedLockAssertion assumeLocked(mLock);
249
250 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
251 [this, enabled]() REQUIRES(mLock) {
252 return mPointerCaptureEnabled &&
253 *mPointerCaptureEnabled ==
254 enabled;
255 })) {
256 FAIL() << "Timed out waiting for setPointerCapture(" << enabled << ") to be called.";
257 }
258 mPointerCaptureEnabled.reset();
259 }
260
261 void assertSetPointerCaptureNotCalled() {
262 std::unique_lock lock(mLock);
263 base::ScopedLockAssertion assumeLocked(mLock);
264
265 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
266 FAIL() << "Expected setPointerCapture(enabled) to not be called, but was called. "
267 "enabled = "
268 << *mPointerCaptureEnabled;
269 }
270 mPointerCaptureEnabled.reset();
271 }
272
arthurhungf452d0b2021-01-06 00:19:52 +0800273 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
274 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800275 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800276 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800277 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800278 }
279
Michael Wrightd02c5b62014-02-10 15:10:22 -0800280private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700281 std::mutex mLock;
282 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
283 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
284 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
285 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800286
Prabir Pradhan99987712020-11-10 18:43:05 -0800287 std::condition_variable mPointerCaptureChangedCondition;
288 std::optional<bool> mPointerCaptureEnabled GUARDED_BY(mLock);
289
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700290 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700291 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000292 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
293 std::queue<sp<IBinder>> mResponsiveWindowTokens GUARDED_BY(mLock);
294 std::queue<int32_t> mAnrMonitorPids GUARDED_BY(mLock);
295 std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700296 std::condition_variable mNotifyAnr;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700297
arthurhungf452d0b2021-01-06 00:19:52 +0800298 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800299 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800300
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600301 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700302 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800303 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800304 }
305
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000306 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700307 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000308 mAnrWindowTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700309 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500310 }
311
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000312 void notifyMonitorUnresponsive(int32_t pid, const std::string&) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500313 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000314 mAnrMonitorPids.push(pid);
315 mNotifyAnr.notify_all();
316 }
317
318 void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {
319 std::scoped_lock lock(mLock);
320 mResponsiveWindowTokens.push(connectionToken);
321 mNotifyAnr.notify_all();
322 }
323
324 void notifyMonitorResponsive(int32_t pid) override {
325 std::scoped_lock lock(mLock);
326 mResponsiveMonitorPids.push(pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500327 mNotifyAnr.notify_all();
328 }
329
330 void notifyNoFocusedWindowAnr(
331 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
332 std::scoped_lock lock(mLock);
333 mAnrApplications.push(applicationHandle);
334 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800335 }
336
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600337 void notifyInputChannelBroken(const sp<IBinder>&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800338
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600339 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700340
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600341 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Chris Yef59a2f42020-10-16 12:55:26 -0700342 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
343 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
344 const std::vector<float>& values) override {}
345
346 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
347 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000348
Chris Yefb552902021-02-03 17:18:37 -0800349 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
350
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600351 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800352 *outConfig = mConfig;
353 }
354
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600355 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700356 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800357 switch (inputEvent->getType()) {
358 case AINPUT_EVENT_TYPE_KEY: {
359 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800360 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800361 break;
362 }
363
364 case AINPUT_EVENT_TYPE_MOTION: {
365 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800366 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800367 break;
368 }
369 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800370 return true;
371 }
372
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600373 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800374
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600375 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800376
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600377 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800378 return 0;
379 }
380
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600381 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800382 return false;
383 }
384
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600385 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
386 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700387 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800388 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
389 * essentially a passthrough for notifySwitch.
390 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800391 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800392 }
393
Sean Stoutb4e0a592021-02-23 07:34:53 -0800394 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800395
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800396 bool checkInjectEventsPermissionNonReentrant(int32_t pid, int32_t uid) override {
397 return pid == INJECTOR_PID && uid == INJECTOR_UID;
398 }
Jackal Guof9696682018-10-05 12:23:23 +0800399
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600400 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700401 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700402 mOnPointerDownToken = newToken;
403 }
404
Prabir Pradhan99987712020-11-10 18:43:05 -0800405 void setPointerCapture(bool enabled) override {
406 std::scoped_lock lock(mLock);
407 mPointerCaptureEnabled = {enabled};
408 mPointerCaptureChangedCondition.notify_all();
409 }
410
arthurhungf452d0b2021-01-06 00:19:52 +0800411 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
412 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800413 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800414 mDropTargetWindowToken = token;
415 }
416
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800417 void assertFilterInputEventWasCalled(int type, nsecs_t eventTime, int32_t action,
418 int32_t displayId) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700419 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800420 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
421 ASSERT_EQ(mFilteredEvent->getType(), type);
422
423 if (type == AINPUT_EVENT_TYPE_KEY) {
424 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*mFilteredEvent);
425 EXPECT_EQ(keyEvent.getEventTime(), eventTime);
426 EXPECT_EQ(keyEvent.getAction(), action);
427 EXPECT_EQ(keyEvent.getDisplayId(), displayId);
428 } else if (type == AINPUT_EVENT_TYPE_MOTION) {
429 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*mFilteredEvent);
430 EXPECT_EQ(motionEvent.getEventTime(), eventTime);
431 EXPECT_EQ(motionEvent.getAction(), action);
432 EXPECT_EQ(motionEvent.getDisplayId(), displayId);
433 } else {
434 FAIL() << "Unknown type: " << type;
435 }
436
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800437 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800438 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800439};
440
Michael Wrightd02c5b62014-02-10 15:10:22 -0800441// --- InputDispatcherTest ---
442
443class InputDispatcherTest : public testing::Test {
444protected:
445 sp<FakeInputDispatcherPolicy> mFakePolicy;
446 sp<InputDispatcher> mDispatcher;
447
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000448 void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800449 mFakePolicy = new FakeInputDispatcherPolicy();
450 mDispatcher = new InputDispatcher(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800451 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000452 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700453 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800454 }
455
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000456 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700457 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800458 mFakePolicy.clear();
459 mDispatcher.clear();
460 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700461
462 /**
463 * Used for debugging when writing the test
464 */
465 void dumpDispatcherState() {
466 std::string dump;
467 mDispatcher->dump(dump);
468 std::stringstream ss(dump);
469 std::string to;
470
471 while (std::getline(ss, to, '\n')) {
472 ALOGE("%s", to.c_str());
473 }
474 }
Vishnu Nair958da932020-08-21 17:12:37 -0700475
chaviw3277faf2021-05-19 16:45:23 -0500476 void setFocusedWindow(const sp<WindowInfoHandle>& window,
477 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700478 FocusRequest request;
479 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000480 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700481 if (focusedWindow) {
482 request.focusedToken = focusedWindow->getToken();
483 }
484 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
485 request.displayId = window->getInfo()->displayId;
486 mDispatcher->setFocusedWindow(request);
487 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800488};
489
Michael Wrightd02c5b62014-02-10 15:10:22 -0800490TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
491 KeyEvent event;
492
493 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800494 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
495 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600496 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
497 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800498 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700499 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800500 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800501 << "Should reject key events with undefined action.";
502
503 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800504 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
505 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600506 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800507 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700508 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800509 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800510 << "Should reject key events with ACTION_MULTIPLE.";
511}
512
513TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
514 MotionEvent event;
515 PointerProperties pointerProperties[MAX_POINTERS + 1];
516 PointerCoords pointerCoords[MAX_POINTERS + 1];
517 for (int i = 0; i <= MAX_POINTERS; i++) {
518 pointerProperties[i].clear();
519 pointerProperties[i].id = i;
520 pointerCoords[i].clear();
521 }
522
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800523 // Some constants commonly used below
524 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
525 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
526 constexpr int32_t metaState = AMETA_NONE;
527 constexpr MotionClassification classification = MotionClassification::NONE;
528
chaviw9eaa22c2020-07-01 16:21:27 -0700529 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800530 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800531 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700532 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
533 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700534 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
535 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700536 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800537 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700538 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800539 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800540 << "Should reject motion events with undefined action.";
541
542 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800543 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700544 AMOTION_EVENT_ACTION_POINTER_DOWN |
545 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700546 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
547 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700548 ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
549 ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500550 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800551 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700552 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800553 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800554 << "Should reject motion events with pointer down index too large.";
555
Garfield Tanfbe732e2020-01-24 11:26:14 -0800556 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700557 AMOTION_EVENT_ACTION_POINTER_DOWN |
558 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700559 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
560 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700561 ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
562 ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500563 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800564 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700565 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800566 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 << "Should reject motion events with pointer down index too small.";
568
569 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800570 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700571 AMOTION_EVENT_ACTION_POINTER_UP |
572 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700573 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
574 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700575 ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
576 ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500577 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800578 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700579 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800580 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800581 << "Should reject motion events with pointer up index too large.";
582
Garfield Tanfbe732e2020-01-24 11:26:14 -0800583 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700584 AMOTION_EVENT_ACTION_POINTER_UP |
585 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700586 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
587 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700588 ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
589 ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500590 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800591 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700592 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800593 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594 << "Should reject motion events with pointer up index too small.";
595
596 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800597 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
598 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700599 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700600 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
601 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700602 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800603 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700604 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800605 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800606 << "Should reject motion events with 0 pointers.";
607
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*/ MAX_POINTERS + 1, 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 more than MAX_POINTERS pointers.";
618
619 // Rejects motion events with invalid pointer ids.
620 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800621 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
622 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700623 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700624 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
625 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700626 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800627 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700628 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800629 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800630 << "Should reject motion events with pointer ids less than 0.";
631
632 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800633 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
634 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700635 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700636 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
637 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700638 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800639 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700640 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800641 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800642 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
643
644 // Rejects motion events with duplicate pointer ids.
645 pointerProperties[0].id = 1;
646 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800647 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
648 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700649 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -0700650 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
651 INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700652 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800653 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700654 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800655 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800656 << "Should reject motion events with duplicate pointer ids.";
657}
658
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800659/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
660
661TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
662 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800663 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800664 mDispatcher->notifyConfigurationChanged(&args);
665 ASSERT_TRUE(mDispatcher->waitForIdle());
666
667 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
668}
669
670TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800671 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
672 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800673 mDispatcher->notifySwitch(&args);
674
675 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
676 args.policyFlags |= POLICY_FLAG_TRUSTED;
677 mFakePolicy->assertNotifySwitchWasCalled(args);
678}
679
Arthur Hungb92218b2018-08-14 12:00:21 +0800680// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700681static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700682static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
Arthur Hungb92218b2018-08-14 12:00:21 +0800683
684class FakeApplicationHandle : public InputApplicationHandle {
685public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700686 FakeApplicationHandle() {
687 mInfo.name = "Fake Application";
688 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500689 mInfo.dispatchingTimeoutMillis =
690 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700691 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800692 virtual ~FakeApplicationHandle() {}
693
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000694 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700695
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500696 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
697 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700698 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800699};
700
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800701class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800702public:
Garfield Tan15601662020-09-22 15:32:38 -0700703 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800704 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700705 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800706 }
707
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800708 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700709 InputEvent* event;
710 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
711 if (!consumeSeq) {
712 return nullptr;
713 }
714 finishEvent(*consumeSeq);
715 return event;
716 }
717
718 /**
719 * Receive an event without acknowledging it.
720 * Return the sequence number that could later be used to send finished signal.
721 */
722 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800723 uint32_t consumeSeq;
724 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800725
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800726 std::chrono::time_point start = std::chrono::steady_clock::now();
727 status_t status = WOULD_BLOCK;
728 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800729 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800730 &event);
731 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
732 if (elapsed > 100ms) {
733 break;
734 }
735 }
736
737 if (status == WOULD_BLOCK) {
738 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700739 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800740 }
741
742 if (status != OK) {
743 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700744 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800745 }
746 if (event == nullptr) {
747 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700748 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800749 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700750 if (outEvent != nullptr) {
751 *outEvent = event;
752 }
753 return consumeSeq;
754 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800755
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700756 /**
757 * To be used together with "receiveEvent" to complete the consumption of an event.
758 */
759 void finishEvent(uint32_t consumeSeq) {
760 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
761 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800762 }
763
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000764 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
765 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
766 ASSERT_EQ(OK, status);
767 }
768
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000769 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
770 std::optional<int32_t> expectedDisplayId,
771 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800772 InputEvent* event = consume();
773
774 ASSERT_NE(nullptr, event) << mName.c_str()
775 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800776 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700777 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800778 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800779
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000780 if (expectedDisplayId.has_value()) {
781 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
782 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800783
Tiger Huang8664f8c2018-10-11 19:14:35 +0800784 switch (expectedEventType) {
785 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800786 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
787 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000788 if (expectedFlags.has_value()) {
789 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
790 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800791 break;
792 }
793 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800794 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
795 EXPECT_EQ(expectedAction, motionEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000796 if (expectedFlags.has_value()) {
797 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
798 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800799 break;
800 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100801 case AINPUT_EVENT_TYPE_FOCUS: {
802 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
803 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800804 case AINPUT_EVENT_TYPE_CAPTURE: {
805 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
806 }
arthurhungb89ccb02020-12-30 16:19:01 +0800807 case AINPUT_EVENT_TYPE_DRAG: {
808 FAIL() << "Use 'consumeDragEvent' for DRAG events";
809 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800810 default: {
811 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
812 }
813 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800814 }
815
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100816 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
817 InputEvent* event = consume();
818 ASSERT_NE(nullptr, event) << mName.c_str()
819 << ": consumer should have returned non-NULL event.";
820 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
821 << "Got " << inputEventTypeToString(event->getType())
822 << " event instead of FOCUS event";
823
824 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
825 << mName.c_str() << ": event displayId should always be NONE.";
826
827 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
828 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
829 EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
830 }
831
Prabir Pradhan99987712020-11-10 18:43:05 -0800832 void consumeCaptureEvent(bool hasCapture) {
833 const 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_CAPTURE, event->getType())
837 << "Got " << inputEventTypeToString(event->getType())
838 << " event instead of CAPTURE event";
839
840 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
841 << mName.c_str() << ": event displayId should always be NONE.";
842
843 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
844 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
845 }
846
arthurhungb89ccb02020-12-30 16:19:01 +0800847 void consumeDragEvent(bool isExiting, float x, float y) {
848 const InputEvent* event = consume();
849 ASSERT_NE(nullptr, event) << mName.c_str()
850 << ": consumer should have returned non-NULL event.";
851 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
852 << "Got " << inputEventTypeToString(event->getType())
853 << " event instead of DRAG event";
854
855 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
856 << mName.c_str() << ": event displayId should always be NONE.";
857
858 const auto& dragEvent = static_cast<const DragEvent&>(*event);
859 EXPECT_EQ(isExiting, dragEvent.isExiting());
860 EXPECT_EQ(x, dragEvent.getX());
861 EXPECT_EQ(y, dragEvent.getY());
862 }
863
chaviwd1c23182019-12-20 18:44:56 -0800864 void assertNoEvents() {
865 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700866 if (event == nullptr) {
867 return;
868 }
869 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
870 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
871 ADD_FAILURE() << "Received key event "
872 << KeyEvent::actionToString(keyEvent.getAction());
873 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
874 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
875 ADD_FAILURE() << "Received motion event "
876 << MotionEvent::actionToString(motionEvent.getAction());
877 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
878 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
879 ADD_FAILURE() << "Received focus event, hasFocus = "
880 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800881 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
882 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
883 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
884 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700885 }
886 FAIL() << mName.c_str()
887 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800888 }
889
890 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
891
892protected:
893 std::unique_ptr<InputConsumer> mConsumer;
894 PreallocatedInputEventFactory mEventFactory;
895
896 std::string mName;
897};
898
chaviw3277faf2021-05-19 16:45:23 -0500899class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -0800900public:
901 static const int32_t WIDTH = 600;
902 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800903
Chris Yea209fde2020-07-22 13:54:51 -0700904 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
chaviwd1c23182019-12-20 18:44:56 -0800905 const sp<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500906 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800907 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500908 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700909 base::Result<std::unique_ptr<InputChannel>> channel =
910 dispatcher->createInputChannel(name);
911 token = (*channel)->getConnectionToken();
912 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800913 }
914
915 inputApplicationHandle->updateInfo();
916 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
917
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500918 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700919 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800920 mInfo.name = name;
chaviw3277faf2021-05-19 16:45:23 -0500921 mInfo.type = WindowInfo::Type::APPLICATION;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500922 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000923 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -0800924 mInfo.frameLeft = 0;
925 mInfo.frameTop = 0;
926 mInfo.frameRight = WIDTH;
927 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700928 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800929 mInfo.globalScaleFactor = 1.0;
930 mInfo.touchableRegion.clear();
931 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
932 mInfo.visible = true;
Vishnu Nair47074b82020-08-14 11:54:47 -0700933 mInfo.focusable = false;
chaviwd1c23182019-12-20 18:44:56 -0800934 mInfo.hasWallpaper = false;
935 mInfo.paused = false;
chaviwd1c23182019-12-20 18:44:56 -0800936 mInfo.ownerPid = INJECTOR_PID;
937 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -0800938 mInfo.displayId = displayId;
939 }
940
Arthur Hungabbb9d82021-09-01 14:52:30 +0000941 sp<FakeWindowHandle> clone(
942 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
943 const sp<InputDispatcher>& dispatcher, int32_t displayId) {
944 sp<FakeWindowHandle> handle =
945 new FakeWindowHandle(inputApplicationHandle, dispatcher, mInfo.name + "(Mirror)",
946 displayId, mInfo.token);
947 return handle;
948 }
949
Vishnu Nair47074b82020-08-14 11:54:47 -0700950 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
chaviwd1c23182019-12-20 18:44:56 -0800951
Vishnu Nair958da932020-08-21 17:12:37 -0700952 void setVisible(bool visible) { mInfo.visible = visible; }
953
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700954 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500955 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700956 }
957
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700958 void setPaused(bool paused) { mInfo.paused = paused; }
959
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000960 void setAlpha(float alpha) { mInfo.alpha = alpha; }
961
chaviw3277faf2021-05-19 16:45:23 -0500962 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000963
Bernardo Rufino7393d172021-02-26 13:56:11 +0000964 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
965
chaviwd1c23182019-12-20 18:44:56 -0800966 void setFrame(const Rect& frame) {
967 mInfo.frameLeft = frame.left;
968 mInfo.frameTop = frame.top;
969 mInfo.frameRight = frame.right;
970 mInfo.frameBottom = frame.bottom;
arthurhungb89ccb02020-12-30 16:19:01 +0800971 mInfo.transform.set(-frame.left, -frame.top);
chaviwd1c23182019-12-20 18:44:56 -0800972 mInfo.touchableRegion.clear();
973 mInfo.addTouchableRegion(frame);
974 }
975
chaviw3277faf2021-05-19 16:45:23 -0500976 void addFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags |= flags; }
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +0000977
chaviw3277faf2021-05-19 16:45:23 -0500978 void setFlags(Flags<WindowInfo::Flag> flags) { mInfo.flags = flags; }
chaviwd1c23182019-12-20 18:44:56 -0800979
chaviw3277faf2021-05-19 16:45:23 -0500980 void setInputFeatures(WindowInfo::Feature features) { mInfo.inputFeatures = features; }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500981
chaviw9eaa22c2020-07-01 16:21:27 -0700982 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
983 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
984 }
985
986 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700987
yunho.shinf4a80b82020-11-16 21:13:57 +0900988 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
989
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800990 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
991 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
992 expectedFlags);
993 }
994
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700995 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
996 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
997 }
998
Svet Ganov5d3bc372020-01-26 23:11:07 -0800999 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001000 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001001 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
1002 expectedFlags);
1003 }
1004
1005 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001006 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001007 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
1008 expectedFlags);
1009 }
1010
1011 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001012 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001013 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1014 }
1015
1016 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1017 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001018 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1019 expectedFlags);
1020 }
1021
Svet Ganov5d3bc372020-01-26 23:11:07 -08001022 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001023 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1024 int32_t expectedFlags = 0) {
1025 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1026 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001027 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1028 }
1029
1030 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001031 int32_t expectedFlags = 0) {
1032 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1033 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001034 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1035 }
1036
1037 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001038 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001039 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1040 expectedFlags);
1041 }
1042
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001043 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1044 int32_t expectedFlags = 0) {
1045 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1046 expectedFlags);
1047 }
1048
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001049 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1050 ASSERT_NE(mInputReceiver, nullptr)
1051 << "Cannot consume events from a window with no receiver";
1052 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1053 }
1054
Prabir Pradhan99987712020-11-10 18:43:05 -08001055 void consumeCaptureEvent(bool hasCapture) {
1056 ASSERT_NE(mInputReceiver, nullptr)
1057 << "Cannot consume events from a window with no receiver";
1058 mInputReceiver->consumeCaptureEvent(hasCapture);
1059 }
1060
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001061 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1062 std::optional<int32_t> expectedDisplayId,
1063 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001064 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1065 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1066 expectedFlags);
1067 }
1068
arthurhungb89ccb02020-12-30 16:19:01 +08001069 void consumeDragEvent(bool isExiting, float x, float y) {
1070 mInputReceiver->consumeDragEvent(isExiting, x, y);
1071 }
1072
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001073 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001074 if (mInputReceiver == nullptr) {
1075 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1076 return std::nullopt;
1077 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001078 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001079 }
1080
1081 void finishEvent(uint32_t sequenceNum) {
1082 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1083 mInputReceiver->finishEvent(sequenceNum);
1084 }
1085
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001086 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1087 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1088 mInputReceiver->sendTimeline(inputEventId, timeline);
1089 }
1090
chaviwaf87b3e2019-10-01 16:59:28 -07001091 InputEvent* consume() {
1092 if (mInputReceiver == nullptr) {
1093 return nullptr;
1094 }
1095 return mInputReceiver->consume();
1096 }
1097
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001098 MotionEvent* consumeMotion() {
1099 InputEvent* event = consume();
1100 if (event == nullptr) {
1101 ADD_FAILURE() << "Consume failed : no event";
1102 return nullptr;
1103 }
1104 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1105 ADD_FAILURE() << "Instead of motion event, got "
1106 << inputEventTypeToString(event->getType());
1107 return nullptr;
1108 }
1109 return static_cast<MotionEvent*>(event);
1110 }
1111
Arthur Hungb92218b2018-08-14 12:00:21 +08001112 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001113 if (mInputReceiver == nullptr &&
chaviw3277faf2021-05-19 16:45:23 -05001114 mInfo.inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001115 return; // Can't receive events if the window does not have input channel
1116 }
1117 ASSERT_NE(nullptr, mInputReceiver)
1118 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001119 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001120 }
1121
chaviwaf87b3e2019-10-01 16:59:28 -07001122 sp<IBinder> getToken() { return mInfo.token; }
1123
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001124 const std::string& getName() { return mName; }
1125
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001126 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1127 mInfo.ownerPid = ownerPid;
1128 mInfo.ownerUid = ownerUid;
1129 }
1130
chaviwd1c23182019-12-20 18:44:56 -08001131private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001132 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001133 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001134 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001135};
1136
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001137std::atomic<int32_t> FakeWindowHandle::sId{1};
1138
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001139static InputEventInjectionResult injectKey(
1140 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
1141 int32_t displayId = ADISPLAY_ID_NONE,
1142 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001143 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1144 bool allowKeyRepeat = true) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001145 KeyEvent event;
1146 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1147
1148 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001149 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001150 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1151 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001152
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001153 int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
1154 if (!allowKeyRepeat) {
1155 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1156 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001157 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001158 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001159 injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001160}
1161
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001162static InputEventInjectionResult injectKeyDown(const sp<InputDispatcher>& dispatcher,
1163 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001164 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1165}
1166
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001167// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1168// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1169// has to be woken up to process the repeating key.
1170static InputEventInjectionResult injectKeyDownNoRepeat(const sp<InputDispatcher>& dispatcher,
1171 int32_t displayId = ADISPLAY_ID_NONE) {
1172 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1173 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1174 /* allowKeyRepeat */ false);
1175}
1176
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001177static InputEventInjectionResult injectKeyUp(const sp<InputDispatcher>& dispatcher,
1178 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001179 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1180}
1181
Garfield Tandf26e862020-07-01 20:18:19 -07001182class PointerBuilder {
1183public:
1184 PointerBuilder(int32_t id, int32_t toolType) {
1185 mProperties.clear();
1186 mProperties.id = id;
1187 mProperties.toolType = toolType;
1188 mCoords.clear();
1189 }
1190
1191 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1192
1193 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1194
1195 PointerBuilder& axis(int32_t axis, float value) {
1196 mCoords.setAxisValue(axis, value);
1197 return *this;
1198 }
1199
1200 PointerProperties buildProperties() const { return mProperties; }
1201
1202 PointerCoords buildCoords() const { return mCoords; }
1203
1204private:
1205 PointerProperties mProperties;
1206 PointerCoords mCoords;
1207};
1208
1209class MotionEventBuilder {
1210public:
1211 MotionEventBuilder(int32_t action, int32_t source) {
1212 mAction = action;
1213 mSource = source;
1214 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1215 }
1216
1217 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1218 mEventTime = eventTime;
1219 return *this;
1220 }
1221
1222 MotionEventBuilder& displayId(int32_t displayId) {
1223 mDisplayId = displayId;
1224 return *this;
1225 }
1226
1227 MotionEventBuilder& actionButton(int32_t actionButton) {
1228 mActionButton = actionButton;
1229 return *this;
1230 }
1231
arthurhung6d4bed92021-03-17 11:59:33 +08001232 MotionEventBuilder& buttonState(int32_t buttonState) {
1233 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001234 return *this;
1235 }
1236
1237 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1238 mRawXCursorPosition = rawXCursorPosition;
1239 return *this;
1240 }
1241
1242 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1243 mRawYCursorPosition = rawYCursorPosition;
1244 return *this;
1245 }
1246
1247 MotionEventBuilder& pointer(PointerBuilder pointer) {
1248 mPointers.push_back(pointer);
1249 return *this;
1250 }
1251
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001252 MotionEventBuilder& addFlag(uint32_t flags) {
1253 mFlags |= flags;
1254 return *this;
1255 }
1256
Garfield Tandf26e862020-07-01 20:18:19 -07001257 MotionEvent build() {
1258 std::vector<PointerProperties> pointerProperties;
1259 std::vector<PointerCoords> pointerCoords;
1260 for (const PointerBuilder& pointer : mPointers) {
1261 pointerProperties.push_back(pointer.buildProperties());
1262 pointerCoords.push_back(pointer.buildCoords());
1263 }
1264
1265 // Set mouse cursor position for the most common cases to avoid boilerplate.
1266 if (mSource == AINPUT_SOURCE_MOUSE &&
1267 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1268 mPointers.size() == 1) {
1269 mRawXCursorPosition = pointerCoords[0].getX();
1270 mRawYCursorPosition = pointerCoords[0].getY();
1271 }
1272
1273 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001274 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001275 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001276 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001277 mButtonState, MotionClassification::NONE, identityTransform,
1278 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Evan Rosky09576692021-07-01 12:22:09 -07001279 mRawYCursorPosition, mDisplayOrientation, mDisplayWidth, mDisplayHeight,
1280 mEventTime, mEventTime, mPointers.size(), pointerProperties.data(),
1281 pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001282
1283 return event;
1284 }
1285
1286private:
1287 int32_t mAction;
1288 int32_t mSource;
1289 nsecs_t mEventTime;
1290 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1291 int32_t mActionButton{0};
1292 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001293 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001294 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1295 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
Evan Rosky09576692021-07-01 12:22:09 -07001296 uint32_t mDisplayOrientation{ui::Transform::ROT_0};
chaviw3277faf2021-05-19 16:45:23 -05001297 int32_t mDisplayWidth{INVALID_DISPLAY_SIZE};
1298 int32_t mDisplayHeight{INVALID_DISPLAY_SIZE};
Garfield Tandf26e862020-07-01 20:18:19 -07001299
1300 std::vector<PointerBuilder> mPointers;
1301};
1302
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001303static InputEventInjectionResult injectMotionEvent(
Garfield Tandf26e862020-07-01 20:18:19 -07001304 const sp<InputDispatcher>& dispatcher, const MotionEvent& event,
1305 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001306 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001307 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1308 injectionTimeout,
1309 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1310}
1311
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001312static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001313 const sp<InputDispatcher>& dispatcher, int32_t action, int32_t source, int32_t displayId,
1314 const PointF& position,
1315 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001316 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1317 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001318 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001319 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001320 MotionEvent event = MotionEventBuilder(action, source)
1321 .displayId(displayId)
1322 .eventTime(eventTime)
1323 .rawXCursorPosition(cursorPosition.x)
1324 .rawYCursorPosition(cursorPosition.y)
1325 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1326 .x(position.x)
1327 .y(position.y))
1328 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001329
1330 // Inject event until dispatch out.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001331 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode);
Arthur Hungb92218b2018-08-14 12:00:21 +08001332}
1333
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001334static InputEventInjectionResult injectMotionDown(const sp<InputDispatcher>& dispatcher,
1335 int32_t source, int32_t displayId,
1336 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001337 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001338}
1339
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001340static InputEventInjectionResult injectMotionUp(const sp<InputDispatcher>& dispatcher,
1341 int32_t source, int32_t displayId,
1342 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001343 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001344}
1345
Jackal Guof9696682018-10-05 12:23:23 +08001346static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1347 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1348 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001349 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1350 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1351 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001352
1353 return args;
1354}
1355
chaviwd1c23182019-12-20 18:44:56 -08001356static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1357 const std::vector<PointF>& points) {
1358 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001359 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1360 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1361 }
1362
chaviwd1c23182019-12-20 18:44:56 -08001363 PointerProperties pointerProperties[pointerCount];
1364 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001365
chaviwd1c23182019-12-20 18:44:56 -08001366 for (size_t i = 0; i < pointerCount; i++) {
1367 pointerProperties[i].clear();
1368 pointerProperties[i].id = i;
1369 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001370
chaviwd1c23182019-12-20 18:44:56 -08001371 pointerCoords[i].clear();
1372 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1373 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1374 }
Jackal Guof9696682018-10-05 12:23:23 +08001375
1376 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1377 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001378 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001379 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1380 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001381 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1382 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001383 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1384 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001385
1386 return args;
1387}
1388
chaviwd1c23182019-12-20 18:44:56 -08001389static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1390 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1391}
1392
Prabir Pradhan99987712020-11-10 18:43:05 -08001393static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(bool enabled) {
1394 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), enabled);
1395}
1396
Arthur Hungb92218b2018-08-14 12:00:21 +08001397TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001399 sp<FakeWindowHandle> window =
1400 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001401
Arthur Hung72d8dc32020-03-28 00:48:39 +00001402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1404 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001406
1407 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001408 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001409}
1410
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001411/**
1412 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1413 * To ensure that window receives only events that were directly inside of it, add
1414 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1415 * when finding touched windows.
1416 * This test serves as a sanity check for the next test, where setInputWindows is
1417 * called twice.
1418 */
1419TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001420 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001421 sp<FakeWindowHandle> window =
1422 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1423 window->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05001424 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001425
1426 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001428 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1429 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001431
1432 // Window should receive motion event.
1433 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1434}
1435
1436/**
1437 * Calling setInputWindows twice, with the same info, should not cause any issues.
1438 * To ensure that window receives only events that were directly inside of it, add
1439 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1440 * when finding touched windows.
1441 */
1442TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001444 sp<FakeWindowHandle> window =
1445 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1446 window->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05001447 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001448
1449 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1450 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001452 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1453 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001454 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001455
1456 // Window should receive motion event.
1457 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1458}
1459
Arthur Hungb92218b2018-08-14 12:00:21 +08001460// The foreground window should receive the first touch down event.
1461TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001462 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001463 sp<FakeWindowHandle> windowTop =
1464 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1465 sp<FakeWindowHandle> windowSecond =
1466 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001467
Arthur Hung72d8dc32020-03-28 00:48:39 +00001468 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1470 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1471 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001472
1473 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001474 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001475 windowSecond->assertNoEvents();
1476}
1477
Garfield Tandf26e862020-07-01 20:18:19 -07001478TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001479 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001480 sp<FakeWindowHandle> windowLeft =
1481 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1482 windowLeft->setFrame(Rect(0, 0, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001483 windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001484 sp<FakeWindowHandle> windowRight =
1485 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1486 windowRight->setFrame(Rect(600, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001487 windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001488
1489 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1490
1491 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1492
1493 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001495 injectMotionEvent(mDispatcher,
1496 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1497 AINPUT_SOURCE_MOUSE)
1498 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1499 .x(900)
1500 .y(400))
1501 .build()));
1502 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1503 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1504 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1505 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1506
1507 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001509 injectMotionEvent(mDispatcher,
1510 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1511 AINPUT_SOURCE_MOUSE)
1512 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1513 .x(300)
1514 .y(400))
1515 .build()));
1516 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1517 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1518 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1519 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1520 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1521 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1522
1523 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001525 injectMotionEvent(mDispatcher,
1526 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1527 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1528 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1529 .x(300)
1530 .y(400))
1531 .build()));
1532 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1533
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001535 injectMotionEvent(mDispatcher,
1536 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1537 AINPUT_SOURCE_MOUSE)
1538 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1539 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1540 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1541 .x(300)
1542 .y(400))
1543 .build()));
1544 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1545 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1546
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001548 injectMotionEvent(mDispatcher,
1549 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1550 AINPUT_SOURCE_MOUSE)
1551 .buttonState(0)
1552 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1553 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1554 .x(300)
1555 .y(400))
1556 .build()));
1557 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1558 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1559
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001560 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001561 injectMotionEvent(mDispatcher,
1562 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1563 .buttonState(0)
1564 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1565 .x(300)
1566 .y(400))
1567 .build()));
1568 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1569
1570 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001571 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001572 injectMotionEvent(mDispatcher,
1573 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1574 AINPUT_SOURCE_MOUSE)
1575 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1576 .x(900)
1577 .y(400))
1578 .build()));
1579 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1580 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1581 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1582 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1583 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1584 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1585}
1586
1587// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1588// directly in this test.
1589TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001591 sp<FakeWindowHandle> window =
1592 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1593 window->setFrame(Rect(0, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001594 window->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tandf26e862020-07-01 20:18:19 -07001595
1596 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1597
1598 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1599
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001601 injectMotionEvent(mDispatcher,
1602 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1603 AINPUT_SOURCE_MOUSE)
1604 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1605 .x(300)
1606 .y(400))
1607 .build()));
1608 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1609 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1610
1611 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001613 injectMotionEvent(mDispatcher,
1614 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1615 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1616 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1617 .x(300)
1618 .y(400))
1619 .build()));
1620 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1621
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001623 injectMotionEvent(mDispatcher,
1624 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1625 AINPUT_SOURCE_MOUSE)
1626 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1627 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1628 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1629 .x(300)
1630 .y(400))
1631 .build()));
1632 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1633 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1634
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001636 injectMotionEvent(mDispatcher,
1637 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1638 AINPUT_SOURCE_MOUSE)
1639 .buttonState(0)
1640 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1641 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1642 .x(300)
1643 .y(400))
1644 .build()));
1645 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1646 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1647
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001649 injectMotionEvent(mDispatcher,
1650 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1651 .buttonState(0)
1652 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1653 .x(300)
1654 .y(400))
1655 .build()));
1656 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1657
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001659 injectMotionEvent(mDispatcher,
1660 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
1661 AINPUT_SOURCE_MOUSE)
1662 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1663 .x(300)
1664 .y(400))
1665 .build()));
1666 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1667 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1668}
1669
Garfield Tan00f511d2019-06-12 16:55:40 -07001670TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07001671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07001672
1673 sp<FakeWindowHandle> windowLeft =
1674 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1675 windowLeft->setFrame(Rect(0, 0, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001676 windowLeft->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001677 sp<FakeWindowHandle> windowRight =
1678 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1679 windowRight->setFrame(Rect(600, 0, 1200, 800));
chaviw3277faf2021-05-19 16:45:23 -05001680 windowRight->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Garfield Tan00f511d2019-06-12 16:55:40 -07001681
1682 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1683
Arthur Hung72d8dc32020-03-28 00:48:39 +00001684 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07001685
1686 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
1687 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07001689 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001690 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001691 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07001692 windowRight->assertNoEvents();
1693}
1694
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001695TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001697 sp<FakeWindowHandle> window =
1698 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07001699 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001700
Arthur Hung72d8dc32020-03-28 00:48:39 +00001701 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07001702 setFocusedWindow(window);
1703
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001704 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001705
1706 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
1707 mDispatcher->notifyKey(&keyArgs);
1708
1709 // Window should receive key down event.
1710 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
1711
1712 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
1713 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001714 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001715 mDispatcher->notifyDeviceReset(&args);
1716 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
1717 AKEY_EVENT_FLAG_CANCELED);
1718}
1719
1720TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07001721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001722 sp<FakeWindowHandle> window =
1723 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1724
Arthur Hung72d8dc32020-03-28 00:48:39 +00001725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001726
1727 NotifyMotionArgs motionArgs =
1728 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1729 ADISPLAY_ID_DEFAULT);
1730 mDispatcher->notifyMotion(&motionArgs);
1731
1732 // Window should receive motion down event.
1733 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1734
1735 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
1736 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08001737 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08001738 mDispatcher->notifyDeviceReset(&args);
1739 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
1740 0 /*expectedFlags*/);
1741}
1742
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001743using TransferFunction =
1744 std::function<bool(sp<InputDispatcher> dispatcher, sp<IBinder>, sp<IBinder>)>;
1745
1746class TransferTouchFixture : public InputDispatcherTest,
1747 public ::testing::WithParamInterface<TransferFunction> {};
1748
1749TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07001750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001751
1752 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001753 sp<FakeWindowHandle> firstWindow =
1754 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1755 sp<FakeWindowHandle> secondWindow =
1756 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001757
1758 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001759 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001760
1761 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001762 NotifyMotionArgs downMotionArgs =
1763 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1764 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001765 mDispatcher->notifyMotion(&downMotionArgs);
1766 // Only the first window should get the down event
1767 firstWindow->consumeMotionDown();
1768 secondWindow->assertNoEvents();
1769
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001770 // Transfer touch to the second window
1771 TransferFunction f = GetParam();
1772 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
1773 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001774 // The first window gets cancel and the second gets down
1775 firstWindow->consumeMotionCancel();
1776 secondWindow->consumeMotionDown();
1777
1778 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001779 NotifyMotionArgs upMotionArgs =
1780 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1781 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001782 mDispatcher->notifyMotion(&upMotionArgs);
1783 // The first window gets no events and the second gets up
1784 firstWindow->assertNoEvents();
1785 secondWindow->consumeMotionUp();
1786}
1787
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001788TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001790
1791 PointF touchPoint = {10, 10};
1792
1793 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001794 sp<FakeWindowHandle> firstWindow =
1795 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1796 sp<FakeWindowHandle> secondWindow =
1797 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001798
1799 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001800 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001801
1802 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001803 NotifyMotionArgs downMotionArgs =
1804 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1805 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001806 mDispatcher->notifyMotion(&downMotionArgs);
1807 // Only the first window should get the down event
1808 firstWindow->consumeMotionDown();
1809 secondWindow->assertNoEvents();
1810
1811 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001812 NotifyMotionArgs pointerDownMotionArgs =
1813 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1814 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1815 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1816 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001817 mDispatcher->notifyMotion(&pointerDownMotionArgs);
1818 // Only the first window should get the pointer down event
1819 firstWindow->consumeMotionPointerDown(1);
1820 secondWindow->assertNoEvents();
1821
1822 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001823 TransferFunction f = GetParam();
1824 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
1825 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001826 // The first window gets cancel and the second gets down and pointer down
1827 firstWindow->consumeMotionCancel();
1828 secondWindow->consumeMotionDown();
1829 secondWindow->consumeMotionPointerDown(1);
1830
1831 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001832 NotifyMotionArgs pointerUpMotionArgs =
1833 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1834 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1835 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1836 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001837 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1838 // The first window gets nothing and the second gets pointer up
1839 firstWindow->assertNoEvents();
1840 secondWindow->consumeMotionPointerUp(1);
1841
1842 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001843 NotifyMotionArgs upMotionArgs =
1844 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1845 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001846 mDispatcher->notifyMotion(&upMotionArgs);
1847 // The first window gets nothing and the second gets up
1848 firstWindow->assertNoEvents();
1849 secondWindow->consumeMotionUp();
1850}
1851
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001852// For the cases of single pointer touch and two pointers non-split touch, the api's
1853// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
1854// for the case where there are multiple pointers split across several windows.
1855INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
1856 ::testing::Values(
1857 [&](sp<InputDispatcher> dispatcher, sp<IBinder> /*ignored*/,
1858 sp<IBinder> destChannelToken) {
1859 return dispatcher->transferTouch(destChannelToken);
1860 },
1861 [&](sp<InputDispatcher> dispatcher, sp<IBinder> from,
1862 sp<IBinder> to) {
1863 return dispatcher->transferTouchFocus(from, to,
1864 false /*isDragAndDrop*/);
1865 }));
1866
Svet Ganov5d3bc372020-01-26 23:11:07 -08001867TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08001869
1870 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001871 sp<FakeWindowHandle> firstWindow =
1872 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001873 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05001874 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001875
1876 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001877 sp<FakeWindowHandle> secondWindow =
1878 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001879 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001880 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001881
1882 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00001883 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001884
1885 PointF pointInFirst = {300, 200};
1886 PointF pointInSecond = {300, 600};
1887
1888 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001889 NotifyMotionArgs firstDownMotionArgs =
1890 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1891 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001892 mDispatcher->notifyMotion(&firstDownMotionArgs);
1893 // Only the first window should get the down event
1894 firstWindow->consumeMotionDown();
1895 secondWindow->assertNoEvents();
1896
1897 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001898 NotifyMotionArgs secondDownMotionArgs =
1899 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1900 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1901 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1902 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001903 mDispatcher->notifyMotion(&secondDownMotionArgs);
1904 // The first window gets a move and the second a down
1905 firstWindow->consumeMotionMove();
1906 secondWindow->consumeMotionDown();
1907
1908 // Transfer touch focus to the second window
1909 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
1910 // The first window gets cancel and the new gets pointer down (it already saw down)
1911 firstWindow->consumeMotionCancel();
1912 secondWindow->consumeMotionPointerDown(1);
1913
1914 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001915 NotifyMotionArgs pointerUpMotionArgs =
1916 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1917 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1918 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1919 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08001920 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1921 // The first window gets nothing and the second gets pointer up
1922 firstWindow->assertNoEvents();
1923 secondWindow->consumeMotionPointerUp(1);
1924
1925 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001926 NotifyMotionArgs upMotionArgs =
1927 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
1928 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001929 mDispatcher->notifyMotion(&upMotionArgs);
1930 // The first window gets nothing and the second gets up
1931 firstWindow->assertNoEvents();
1932 secondWindow->consumeMotionUp();
1933}
1934
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001935// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
1936// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
1937// touch is not supported, so the touch should continue on those windows and the transferred-to
1938// window should get nothing.
1939TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
1940 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1941
1942 // Create a non touch modal window that supports split touch
1943 sp<FakeWindowHandle> firstWindow =
1944 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
1945 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05001946 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001947
1948 // Create a non touch modal window that supports split touch
1949 sp<FakeWindowHandle> secondWindow =
1950 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
1951 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05001952 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00001953
1954 // Add the windows to the dispatcher
1955 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
1956
1957 PointF pointInFirst = {300, 200};
1958 PointF pointInSecond = {300, 600};
1959
1960 // Send down to the first window
1961 NotifyMotionArgs firstDownMotionArgs =
1962 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
1963 ADISPLAY_ID_DEFAULT, {pointInFirst});
1964 mDispatcher->notifyMotion(&firstDownMotionArgs);
1965 // Only the first window should get the down event
1966 firstWindow->consumeMotionDown();
1967 secondWindow->assertNoEvents();
1968
1969 // Send down to the second window
1970 NotifyMotionArgs secondDownMotionArgs =
1971 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
1972 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1973 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1974 {pointInFirst, pointInSecond});
1975 mDispatcher->notifyMotion(&secondDownMotionArgs);
1976 // The first window gets a move and the second a down
1977 firstWindow->consumeMotionMove();
1978 secondWindow->consumeMotionDown();
1979
1980 // Transfer touch focus to the second window
1981 const bool transferred = mDispatcher->transferTouch(secondWindow->getToken());
1982 // The 'transferTouch' call should not succeed, because there are 2 touched windows
1983 ASSERT_FALSE(transferred);
1984 firstWindow->assertNoEvents();
1985 secondWindow->assertNoEvents();
1986
1987 // The rest of the dispatch should proceed as normal
1988 // Send pointer up to the second window
1989 NotifyMotionArgs pointerUpMotionArgs =
1990 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
1991 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1992 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1993 {pointInFirst, pointInSecond});
1994 mDispatcher->notifyMotion(&pointerUpMotionArgs);
1995 // The first window gets MOVE and the second gets pointer up
1996 firstWindow->consumeMotionMove();
1997 secondWindow->consumeMotionUp();
1998
1999 // Send up event to the first window
2000 NotifyMotionArgs upMotionArgs =
2001 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2002 ADISPLAY_ID_DEFAULT);
2003 mDispatcher->notifyMotion(&upMotionArgs);
2004 // The first window gets nothing and the second gets up
2005 firstWindow->consumeMotionUp();
2006 secondWindow->assertNoEvents();
2007}
2008
Arthur Hungabbb9d82021-09-01 14:52:30 +00002009// This case will create two windows and one mirrored window on the default display and mirror
2010// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
2011// the windows info of second display before default display.
2012TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
2013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2014 sp<FakeWindowHandle> firstWindowInPrimary =
2015 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2016 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
2017 firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2018 sp<FakeWindowHandle> secondWindowInPrimary =
2019 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2020 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2021 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2022
2023 sp<FakeWindowHandle> mirrorWindowInPrimary =
2024 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2025 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
2026 mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2027
2028 sp<FakeWindowHandle> firstWindowInSecondary =
2029 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2030 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
2031 firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2032
2033 sp<FakeWindowHandle> secondWindowInSecondary =
2034 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2035 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2036 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2037
2038 // Update window info, let it find window handle of second display first.
2039 mDispatcher->setInputWindows(
2040 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2041 {ADISPLAY_ID_DEFAULT,
2042 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2043
2044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2045 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2046 {50, 50}))
2047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2048
2049 // Window should receive motion event.
2050 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2051
2052 // Transfer touch focus
2053 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
2054 secondWindowInPrimary->getToken()));
2055 // The first window gets cancel.
2056 firstWindowInPrimary->consumeMotionCancel();
2057 secondWindowInPrimary->consumeMotionDown();
2058
2059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2060 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2061 ADISPLAY_ID_DEFAULT, {150, 50}))
2062 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2063 firstWindowInPrimary->assertNoEvents();
2064 secondWindowInPrimary->consumeMotionMove();
2065
2066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2067 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2068 {150, 50}))
2069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2070 firstWindowInPrimary->assertNoEvents();
2071 secondWindowInPrimary->consumeMotionUp();
2072}
2073
2074// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
2075// 'transferTouch' api.
2076TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
2077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2078 sp<FakeWindowHandle> firstWindowInPrimary =
2079 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2080 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
2081 firstWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2082 sp<FakeWindowHandle> secondWindowInPrimary =
2083 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2084 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2085 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2086
2087 sp<FakeWindowHandle> mirrorWindowInPrimary =
2088 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2089 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
2090 mirrorWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2091
2092 sp<FakeWindowHandle> firstWindowInSecondary =
2093 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2094 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
2095 firstWindowInSecondary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2096
2097 sp<FakeWindowHandle> secondWindowInSecondary =
2098 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2099 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
2100 secondWindowInPrimary->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
2101
2102 // Update window info, let it find window handle of second display first.
2103 mDispatcher->setInputWindows(
2104 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2105 {ADISPLAY_ID_DEFAULT,
2106 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2107
2108 // Touch on second display.
2109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2110 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
2111 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2112
2113 // Window should receive motion event.
2114 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2115
2116 // Transfer touch focus
2117 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken()));
2118
2119 // The first window gets cancel.
2120 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
2121 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2122
2123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2124 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2125 SECOND_DISPLAY_ID, {150, 50}))
2126 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2127 firstWindowInPrimary->assertNoEvents();
2128 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
2129
2130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2131 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
2132 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2133 firstWindowInPrimary->assertNoEvents();
2134 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
2135}
2136
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002137TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002138 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002139 sp<FakeWindowHandle> window =
2140 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2141
Vishnu Nair47074b82020-08-14 11:54:47 -07002142 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002143 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002144 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002145
2146 window->consumeFocusEvent(true);
2147
2148 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2149 mDispatcher->notifyKey(&keyArgs);
2150
2151 // Window should receive key down event.
2152 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2153}
2154
2155TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002157 sp<FakeWindowHandle> window =
2158 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2159
Arthur Hung72d8dc32020-03-28 00:48:39 +00002160 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002161
2162 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2163 mDispatcher->notifyKey(&keyArgs);
2164 mDispatcher->waitForIdle();
2165
2166 window->assertNoEvents();
2167}
2168
2169// If a window is touchable, but does not have focus, it should receive motion events, but not keys
2170TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07002171 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002172 sp<FakeWindowHandle> window =
2173 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2174
Arthur Hung72d8dc32020-03-28 00:48:39 +00002175 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002176
2177 // Send key
2178 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2179 mDispatcher->notifyKey(&keyArgs);
2180 // Send motion
2181 NotifyMotionArgs motionArgs =
2182 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2183 ADISPLAY_ID_DEFAULT);
2184 mDispatcher->notifyMotion(&motionArgs);
2185
2186 // Window should receive only the motion event
2187 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2188 window->assertNoEvents(); // Key event or focus event will not be received
2189}
2190
arthurhungea3f4fc2020-12-21 23:18:53 +08002191TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
2192 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2193
2194 // Create first non touch modal window that supports split touch
2195 sp<FakeWindowHandle> firstWindow =
2196 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2197 firstWindow->setFrame(Rect(0, 0, 600, 400));
chaviw3277faf2021-05-19 16:45:23 -05002198 firstWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
arthurhungea3f4fc2020-12-21 23:18:53 +08002199
2200 // Create second non touch modal window that supports split touch
2201 sp<FakeWindowHandle> secondWindow =
2202 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2203 secondWindow->setFrame(Rect(0, 400, 600, 800));
chaviw3277faf2021-05-19 16:45:23 -05002204 secondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
arthurhungea3f4fc2020-12-21 23:18:53 +08002205
2206 // Add the windows to the dispatcher
2207 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2208
2209 PointF pointInFirst = {300, 200};
2210 PointF pointInSecond = {300, 600};
2211
2212 // Send down to the first window
2213 NotifyMotionArgs firstDownMotionArgs =
2214 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2215 ADISPLAY_ID_DEFAULT, {pointInFirst});
2216 mDispatcher->notifyMotion(&firstDownMotionArgs);
2217 // Only the first window should get the down event
2218 firstWindow->consumeMotionDown();
2219 secondWindow->assertNoEvents();
2220
2221 // Send down to the second window
2222 NotifyMotionArgs secondDownMotionArgs =
2223 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2224 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2225 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2226 {pointInFirst, pointInSecond});
2227 mDispatcher->notifyMotion(&secondDownMotionArgs);
2228 // The first window gets a move and the second a down
2229 firstWindow->consumeMotionMove();
2230 secondWindow->consumeMotionDown();
2231
2232 // Send pointer cancel to the second window
2233 NotifyMotionArgs pointerUpMotionArgs =
2234 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2235 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2236 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2237 {pointInFirst, pointInSecond});
2238 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
2239 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2240 // The first window gets move and the second gets cancel.
2241 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2242 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2243
2244 // Send up event.
2245 NotifyMotionArgs upMotionArgs =
2246 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2247 ADISPLAY_ID_DEFAULT);
2248 mDispatcher->notifyMotion(&upMotionArgs);
2249 // The first window gets up and the second gets nothing.
2250 firstWindow->consumeMotionUp();
2251 secondWindow->assertNoEvents();
2252}
2253
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00002254TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
2255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2256
2257 sp<FakeWindowHandle> window =
2258 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2259 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2260 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
2261 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
2262 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
2263
2264 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
2265 window->assertNoEvents();
2266 mDispatcher->waitForIdle();
2267}
2268
chaviwd1c23182019-12-20 18:44:56 -08002269class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00002270public:
2271 FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
chaviwd1c23182019-12-20 18:44:56 -08002272 int32_t displayId, bool isGestureMonitor = false) {
Garfield Tan15601662020-09-22 15:32:38 -07002273 base::Result<std::unique_ptr<InputChannel>> channel =
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +00002274 dispatcher->createInputMonitor(displayId, isGestureMonitor, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07002275 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00002276 }
2277
chaviwd1c23182019-12-20 18:44:56 -08002278 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
2279
2280 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2281 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
2282 expectedDisplayId, expectedFlags);
2283 }
2284
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002285 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
2286
2287 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
2288
chaviwd1c23182019-12-20 18:44:56 -08002289 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2290 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
2291 expectedDisplayId, expectedFlags);
2292 }
2293
2294 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2295 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
2296 expectedDisplayId, expectedFlags);
2297 }
2298
Evan Rosky84f07f02021-04-16 10:42:42 -07002299 MotionEvent* consumeMotion() {
2300 InputEvent* event = mInputReceiver->consume();
2301 if (!event) {
2302 ADD_FAILURE() << "No event was produced";
2303 return nullptr;
2304 }
2305 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
2306 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
2307 return nullptr;
2308 }
2309 return static_cast<MotionEvent*>(event);
2310 }
2311
chaviwd1c23182019-12-20 18:44:56 -08002312 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
2313
2314private:
2315 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00002316};
2317
2318// Tests for gesture monitors
2319TEST_F(InputDispatcherTest, GestureMonitor_ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002320 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002321 sp<FakeWindowHandle> window =
2322 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002323 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002324
chaviwd1c23182019-12-20 18:44:56 -08002325 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2326 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002327
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002329 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002331 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002332 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002333}
2334
2335TEST_F(InputDispatcherTest, GestureMonitor_DoesNotReceiveKeyEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002336 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002337 sp<FakeWindowHandle> window =
2338 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2339
2340 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002341 window->setFocusable(true);
Michael Wright3a240c42019-12-10 20:53:41 +00002342
Arthur Hung72d8dc32020-03-28 00:48:39 +00002343 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002344 setFocusedWindow(window);
2345
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002346 window->consumeFocusEvent(true);
Michael Wright3a240c42019-12-10 20:53:41 +00002347
chaviwd1c23182019-12-20 18:44:56 -08002348 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2349 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002350
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002351 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
2352 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002353 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002354 monitor.assertNoEvents();
Michael Wright3a240c42019-12-10 20:53:41 +00002355}
2356
2357TEST_F(InputDispatcherTest, GestureMonitor_CanPilferAfterWindowIsRemovedMidStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002359 sp<FakeWindowHandle> window =
2360 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002361 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002362
chaviwd1c23182019-12-20 18:44:56 -08002363 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2364 true /*isGestureMonitor*/);
Michael Wright3a240c42019-12-10 20:53:41 +00002365
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002367 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002368 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002369 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002370 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002371
2372 window->releaseChannel();
2373
chaviwd1c23182019-12-20 18:44:56 -08002374 mDispatcher->pilferPointers(monitor.getToken());
Michael Wright3a240c42019-12-10 20:53:41 +00002375
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002377 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08002379 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002380}
2381
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002382TEST_F(InputDispatcherTest, UnresponsiveGestureMonitor_GetsAnr) {
2383 FakeMonitorReceiver monitor =
2384 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
2385 true /*isGestureMonitor*/);
2386
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002388 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
2389 std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
2390 ASSERT_TRUE(consumeSeq);
2391
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002392 mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(DISPATCHING_TIMEOUT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002393 monitor.finishEvent(*consumeSeq);
2394 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00002395 mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002396}
2397
Evan Rosky84f07f02021-04-16 10:42:42 -07002398// Tests for gesture monitors
2399TEST_F(InputDispatcherTest, GestureMonitor_NoWindowTransform) {
2400 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2401 sp<FakeWindowHandle> window =
2402 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2403 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2404 window->setWindowOffset(20, 40);
2405 window->setWindowTransform(0, 1, -1, 0);
2406
2407 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "GM_1", ADISPLAY_ID_DEFAULT,
2408 true /*isGestureMonitor*/);
2409
2410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2411 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2412 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2413 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2414 MotionEvent* event = monitor.consumeMotion();
2415 // Even though window has transform, gesture monitor must not.
2416 ASSERT_EQ(ui::Transform(), event->getTransform());
2417}
2418
chaviw81e2bb92019-12-18 15:03:51 -08002419TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002420 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08002421 sp<FakeWindowHandle> window =
2422 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2423
Arthur Hung72d8dc32020-03-28 00:48:39 +00002424 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08002425
2426 NotifyMotionArgs motionArgs =
2427 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2428 ADISPLAY_ID_DEFAULT);
2429
2430 mDispatcher->notifyMotion(&motionArgs);
2431 // Window should receive motion down event.
2432 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2433
2434 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002435 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08002436 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2437 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
2438 motionArgs.pointerCoords[0].getX() - 10);
2439
2440 mDispatcher->notifyMotion(&motionArgs);
2441 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
2442 0 /*expectedFlags*/);
2443}
2444
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002445/**
2446 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
2447 * the device default right away. In the test scenario, we check both the default value,
2448 * and the action of enabling / disabling.
2449 */
2450TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07002451 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002452 sp<FakeWindowHandle> window =
2453 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2454
2455 // Set focused application.
2456 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002457 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002458
2459 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00002460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002461 setFocusedWindow(window);
2462
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002463 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2464
2465 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002466 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002467 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002468 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
2469
2470 SCOPED_TRACE("Disable touch mode");
2471 mDispatcher->setInTouchMode(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07002472 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002473 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002474 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002475 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
2476
2477 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002478 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002479 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002480 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
2481
2482 SCOPED_TRACE("Enable touch mode again");
2483 mDispatcher->setInTouchMode(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07002484 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002485 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002486 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002487 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2488
2489 window->assertNoEvents();
2490}
2491
Gang Wange9087892020-01-07 12:17:14 -05002492TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05002494 sp<FakeWindowHandle> window =
2495 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2496
2497 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002498 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05002499
Arthur Hung72d8dc32020-03-28 00:48:39 +00002500 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002501 setFocusedWindow(window);
2502
Gang Wange9087892020-01-07 12:17:14 -05002503 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2504
2505 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
2506 mDispatcher->notifyKey(&keyArgs);
2507
2508 InputEvent* event = window->consume();
2509 ASSERT_NE(event, nullptr);
2510
2511 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2512 ASSERT_NE(verified, nullptr);
2513 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
2514
2515 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
2516 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
2517 ASSERT_EQ(keyArgs.source, verified->source);
2518 ASSERT_EQ(keyArgs.displayId, verified->displayId);
2519
2520 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
2521
2522 ASSERT_EQ(keyArgs.action, verifiedKey.action);
2523 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05002524 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
2525 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
2526 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
2527 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
2528 ASSERT_EQ(0, verifiedKey.repeatCount);
2529}
2530
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002531TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002532 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002533 sp<FakeWindowHandle> window =
2534 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2535
2536 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2537
Arthur Hung72d8dc32020-03-28 00:48:39 +00002538 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08002539
2540 NotifyMotionArgs motionArgs =
2541 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2542 ADISPLAY_ID_DEFAULT);
2543 mDispatcher->notifyMotion(&motionArgs);
2544
2545 InputEvent* event = window->consume();
2546 ASSERT_NE(event, nullptr);
2547
2548 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
2549 ASSERT_NE(verified, nullptr);
2550 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
2551
2552 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
2553 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
2554 EXPECT_EQ(motionArgs.source, verified->source);
2555 EXPECT_EQ(motionArgs.displayId, verified->displayId);
2556
2557 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
2558
2559 EXPECT_EQ(motionArgs.pointerCoords[0].getX(), verifiedMotion.rawX);
2560 EXPECT_EQ(motionArgs.pointerCoords[0].getY(), verifiedMotion.rawY);
2561 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
2562 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
2563 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
2564 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
2565 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
2566}
2567
Prabir Pradhan664834b2021-05-20 16:00:42 -07002568TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickAndTouchpadNotTransformed) {
yunho.shinf4a80b82020-11-16 21:13:57 +09002569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2570 sp<FakeWindowHandle> window =
2571 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
2572 const std::string name = window->getName();
2573
2574 // Window gets transformed by offset values.
2575 window->setWindowOffset(500.0f, 500.0f);
2576
2577 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2578 window->setFocusable(true);
2579
2580 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2581
2582 // First, we set focused window so that focusedWindowHandle is not null.
2583 setFocusedWindow(window);
2584
2585 // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
2586 window->consumeFocusEvent(true);
2587
Prabir Pradhan664834b2021-05-20 16:00:42 -07002588 constexpr const std::array nonTransformedSources = {std::pair(AINPUT_SOURCE_TOUCHPAD,
2589 AMOTION_EVENT_ACTION_DOWN),
2590 std::pair(AINPUT_SOURCE_JOYSTICK,
2591 AMOTION_EVENT_ACTION_MOVE)};
2592 for (const auto& [source, action] : nonTransformedSources) {
2593 const NotifyMotionArgs motionArgs = generateMotionArgs(action, source, ADISPLAY_ID_DEFAULT);
Prabir Pradhanbd527712021-03-09 19:17:09 -08002594 mDispatcher->notifyMotion(&motionArgs);
yunho.shinf4a80b82020-11-16 21:13:57 +09002595
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002596 MotionEvent* event = window->consumeMotion();
Prabir Pradhanbd527712021-03-09 19:17:09 -08002597 ASSERT_NE(event, nullptr);
yunho.shinf4a80b82020-11-16 21:13:57 +09002598
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00002599 const MotionEvent& motionEvent = *event;
Prabir Pradhan664834b2021-05-20 16:00:42 -07002600 EXPECT_EQ(action, motionEvent.getAction());
Prabir Pradhanbd527712021-03-09 19:17:09 -08002601 EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
yunho.shinf4a80b82020-11-16 21:13:57 +09002602
Prabir Pradhanbd527712021-03-09 19:17:09 -08002603 float expectedX = motionArgs.pointerCoords[0].getX();
2604 float expectedY = motionArgs.pointerCoords[0].getY();
yunho.shinf4a80b82020-11-16 21:13:57 +09002605
Prabir Pradhanbd527712021-03-09 19:17:09 -08002606 // Ensure the axis values from the final motion event are not transformed.
2607 EXPECT_EQ(expectedX, motionEvent.getX(0))
2608 << "expected " << expectedX << " for x coord of " << name.c_str() << ", got "
2609 << motionEvent.getX(0);
2610 EXPECT_EQ(expectedY, motionEvent.getY(0))
2611 << "expected " << expectedY << " for y coord of " << name.c_str() << ", got "
2612 << motionEvent.getY(0);
2613 // Ensure the raw and transformed axis values for the motion event are the same.
2614 EXPECT_EQ(motionEvent.getRawX(0), motionEvent.getX(0))
2615 << "expected raw and transformed X-axis values to be equal";
2616 EXPECT_EQ(motionEvent.getRawY(0), motionEvent.getY(0))
2617 << "expected raw and transformed Y-axis values to be equal";
2618 }
yunho.shinf4a80b82020-11-16 21:13:57 +09002619}
2620
chaviw09c8d2d2020-08-24 15:48:26 -07002621/**
2622 * Ensure that separate calls to sign the same data are generating the same key.
2623 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
2624 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
2625 * tests.
2626 */
2627TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
2628 KeyEvent event = getTestKeyEvent();
2629 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2630
2631 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
2632 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
2633 ASSERT_EQ(hmac1, hmac2);
2634}
2635
2636/**
2637 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
2638 */
2639TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
2640 KeyEvent event = getTestKeyEvent();
2641 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
2642 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
2643
2644 verifiedEvent.deviceId += 1;
2645 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2646
2647 verifiedEvent.source += 1;
2648 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2649
2650 verifiedEvent.eventTimeNanos += 1;
2651 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2652
2653 verifiedEvent.displayId += 1;
2654 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2655
2656 verifiedEvent.action += 1;
2657 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2658
2659 verifiedEvent.downTimeNanos += 1;
2660 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2661
2662 verifiedEvent.flags += 1;
2663 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2664
2665 verifiedEvent.keyCode += 1;
2666 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2667
2668 verifiedEvent.scanCode += 1;
2669 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2670
2671 verifiedEvent.metaState += 1;
2672 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2673
2674 verifiedEvent.repeatCount += 1;
2675 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
2676}
2677
Vishnu Nair958da932020-08-21 17:12:37 -07002678TEST_F(InputDispatcherTest, SetFocusedWindow) {
2679 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2680 sp<FakeWindowHandle> windowTop =
2681 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2682 sp<FakeWindowHandle> windowSecond =
2683 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2684 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2685
2686 // Top window is also focusable but is not granted focus.
2687 windowTop->setFocusable(true);
2688 windowSecond->setFocusable(true);
2689 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2690 setFocusedWindow(windowSecond);
2691
2692 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2694 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002695
2696 // Focused window should receive event.
2697 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2698 windowTop->assertNoEvents();
2699}
2700
2701TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
2702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2703 sp<FakeWindowHandle> window =
2704 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2705 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2706
2707 window->setFocusable(true);
2708 // Release channel for window is no longer valid.
2709 window->releaseChannel();
2710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2711 setFocusedWindow(window);
2712
2713 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002714 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2715 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002716
2717 // window channel is invalid, so it should not receive any input event.
2718 window->assertNoEvents();
2719}
2720
2721TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
2722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2723 sp<FakeWindowHandle> window =
2724 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2725 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2726
2727 // Window is not focusable.
2728 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2729 setFocusedWindow(window);
2730
2731 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002732 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2733 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002734
2735 // window is invalid, so it should not receive any input event.
2736 window->assertNoEvents();
2737}
2738
2739TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
2740 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2741 sp<FakeWindowHandle> windowTop =
2742 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2743 sp<FakeWindowHandle> windowSecond =
2744 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2745 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2746
2747 windowTop->setFocusable(true);
2748 windowSecond->setFocusable(true);
2749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2750 setFocusedWindow(windowTop);
2751 windowTop->consumeFocusEvent(true);
2752
2753 setFocusedWindow(windowSecond, windowTop);
2754 windowSecond->consumeFocusEvent(true);
2755 windowTop->consumeFocusEvent(false);
2756
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
2758 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07002759
2760 // Focused window should receive event.
2761 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
2762}
2763
2764TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
2765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2766 sp<FakeWindowHandle> windowTop =
2767 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
2768 sp<FakeWindowHandle> windowSecond =
2769 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2770 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2771
2772 windowTop->setFocusable(true);
2773 windowSecond->setFocusable(true);
2774 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
2775 setFocusedWindow(windowSecond, windowTop);
2776
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002777 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
2778 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07002779
2780 // Event should be dropped.
2781 windowTop->assertNoEvents();
2782 windowSecond->assertNoEvents();
2783}
2784
2785TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
2786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2787 sp<FakeWindowHandle> window =
2788 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
2789 sp<FakeWindowHandle> previousFocusedWindow =
2790 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
2791 ADISPLAY_ID_DEFAULT);
2792 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2793
2794 window->setFocusable(true);
2795 previousFocusedWindow->setFocusable(true);
2796 window->setVisible(false);
2797 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
2798 setFocusedWindow(previousFocusedWindow);
2799 previousFocusedWindow->consumeFocusEvent(true);
2800
2801 // Requesting focus on invisible window takes focus from currently focused window.
2802 setFocusedWindow(window);
2803 previousFocusedWindow->consumeFocusEvent(false);
2804
2805 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07002807 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002808 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07002809
2810 // Window does not get focus event or key down.
2811 window->assertNoEvents();
2812
2813 // Window becomes visible.
2814 window->setVisible(true);
2815 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2816
2817 // Window receives focus event.
2818 window->consumeFocusEvent(true);
2819 // Focused window receives key down.
2820 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2821}
2822
Vishnu Nair599f1412021-06-21 10:39:58 -07002823TEST_F(InputDispatcherTest, DisplayRemoved) {
2824 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2825 sp<FakeWindowHandle> window =
2826 new FakeWindowHandle(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
2827 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2828
2829 // window is granted focus.
2830 window->setFocusable(true);
2831 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2832 setFocusedWindow(window);
2833 window->consumeFocusEvent(true);
2834
2835 // When a display is removed window loses focus.
2836 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
2837 window->consumeFocusEvent(false);
2838}
2839
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002840/**
2841 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
2842 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
2843 * of the 'slipperyEnterWindow'.
2844 *
2845 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
2846 * a way so that the touched location is no longer covered by the top window.
2847 *
2848 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
2849 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
2850 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
2851 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
2852 * with ACTION_DOWN).
2853 * Thus, the touch has been transferred from the top window into the bottom window, because the top
2854 * window moved itself away from the touched location and had Flag::SLIPPERY.
2855 *
2856 * Even though the top window moved away from the touched location, it is still obscuring the bottom
2857 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
2858 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
2859 *
2860 * In this test, we ensure that the event received by the bottom window has
2861 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
2862 */
2863TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
2864 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
2865 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
2866
2867 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2868 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2869
2870 sp<FakeWindowHandle> slipperyExitWindow =
2871 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviw3277faf2021-05-19 16:45:23 -05002872 slipperyExitWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SLIPPERY);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002873 // Make sure this one overlaps the bottom window
2874 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
2875 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
2876 // one. Windows with the same owner are not considered to be occluding each other.
2877 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
2878
2879 sp<FakeWindowHandle> slipperyEnterWindow =
2880 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
2881 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
2882
2883 mDispatcher->setInputWindows(
2884 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2885
2886 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
2887 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2888 ADISPLAY_ID_DEFAULT, {{50, 50}});
2889 mDispatcher->notifyMotion(&args);
2890 slipperyExitWindow->consumeMotionDown();
2891 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
2892 mDispatcher->setInputWindows(
2893 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
2894
2895 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2896 ADISPLAY_ID_DEFAULT, {{51, 51}});
2897 mDispatcher->notifyMotion(&args);
2898
2899 slipperyExitWindow->consumeMotionCancel();
2900
2901 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
2902 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
2903}
2904
Garfield Tan1c7bc862020-01-28 13:24:04 -08002905class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
2906protected:
2907 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
2908 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
2909
Chris Yea209fde2020-07-22 13:54:51 -07002910 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002911 sp<FakeWindowHandle> mWindow;
2912
2913 virtual void SetUp() override {
2914 mFakePolicy = new FakeInputDispatcherPolicy();
2915 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
2916 mDispatcher = new InputDispatcher(mFakePolicy);
2917 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
2918 ASSERT_EQ(OK, mDispatcher->start());
2919
2920 setUpWindow();
2921 }
2922
2923 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07002924 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08002925 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2926
Vishnu Nair47074b82020-08-14 11:54:47 -07002927 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002928 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002929 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002930 mWindow->consumeFocusEvent(true);
2931 }
2932
Chris Ye2ad95392020-09-01 13:44:44 -07002933 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002934 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002935 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002936 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
2937 mDispatcher->notifyKey(&keyArgs);
2938
2939 // Window should receive key down event.
2940 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2941 }
2942
2943 void expectKeyRepeatOnce(int32_t repeatCount) {
2944 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
2945 InputEvent* repeatEvent = mWindow->consume();
2946 ASSERT_NE(nullptr, repeatEvent);
2947
2948 uint32_t eventType = repeatEvent->getType();
2949 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
2950
2951 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
2952 uint32_t eventAction = repeatKeyEvent->getAction();
2953 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
2954 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
2955 }
2956
Chris Ye2ad95392020-09-01 13:44:44 -07002957 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08002958 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07002959 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08002960 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
2961 mDispatcher->notifyKey(&keyArgs);
2962
2963 // Window should receive key down event.
2964 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2965 0 /*expectedFlags*/);
2966 }
2967};
2968
2969TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07002970 sendAndConsumeKeyDown(1 /* deviceId */);
2971 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2972 expectKeyRepeatOnce(repeatCount);
2973 }
2974}
2975
2976TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
2977 sendAndConsumeKeyDown(1 /* deviceId */);
2978 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2979 expectKeyRepeatOnce(repeatCount);
2980 }
2981 sendAndConsumeKeyDown(2 /* deviceId */);
2982 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08002983 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
2984 expectKeyRepeatOnce(repeatCount);
2985 }
2986}
2987
2988TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07002989 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08002990 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07002991 sendAndConsumeKeyUp(1 /* deviceId */);
2992 mWindow->assertNoEvents();
2993}
2994
2995TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
2996 sendAndConsumeKeyDown(1 /* deviceId */);
2997 expectKeyRepeatOnce(1 /*repeatCount*/);
2998 sendAndConsumeKeyDown(2 /* deviceId */);
2999 expectKeyRepeatOnce(1 /*repeatCount*/);
3000 // Stale key up from device 1.
3001 sendAndConsumeKeyUp(1 /* deviceId */);
3002 // Device 2 is still down, keep repeating
3003 expectKeyRepeatOnce(2 /*repeatCount*/);
3004 expectKeyRepeatOnce(3 /*repeatCount*/);
3005 // Device 2 key up
3006 sendAndConsumeKeyUp(2 /* deviceId */);
3007 mWindow->assertNoEvents();
3008}
3009
3010TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
3011 sendAndConsumeKeyDown(1 /* deviceId */);
3012 expectKeyRepeatOnce(1 /*repeatCount*/);
3013 sendAndConsumeKeyDown(2 /* deviceId */);
3014 expectKeyRepeatOnce(1 /*repeatCount*/);
3015 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
3016 sendAndConsumeKeyUp(2 /* deviceId */);
3017 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08003018 mWindow->assertNoEvents();
3019}
3020
3021TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07003022 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003023 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3024 InputEvent* repeatEvent = mWindow->consume();
3025 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3026 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
3027 IdGenerator::getSource(repeatEvent->getId()));
3028 }
3029}
3030
3031TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07003032 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003033
3034 std::unordered_set<int32_t> idSet;
3035 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3036 InputEvent* repeatEvent = mWindow->consume();
3037 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3038 int32_t id = repeatEvent->getId();
3039 EXPECT_EQ(idSet.end(), idSet.find(id));
3040 idSet.insert(id);
3041 }
3042}
3043
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003044/* Test InputDispatcher for MultiDisplay */
3045class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
3046public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003047 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003048 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08003049
Chris Yea209fde2020-07-22 13:54:51 -07003050 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003051 windowInPrimary =
3052 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003053
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003054 // Set focus window for primary display, but focused display would be second one.
3055 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07003056 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003057 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003058 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003059 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08003060
Chris Yea209fde2020-07-22 13:54:51 -07003061 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003062 windowInSecondary =
3063 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003064 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003065 // Set focus display to second one.
3066 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
3067 // Set focus window for second display.
3068 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07003069 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003070 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003071 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003072 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003073 }
3074
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003075 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003076 InputDispatcherTest::TearDown();
3077
Chris Yea209fde2020-07-22 13:54:51 -07003078 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003079 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07003080 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003081 windowInSecondary.clear();
3082 }
3083
3084protected:
Chris Yea209fde2020-07-22 13:54:51 -07003085 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003086 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07003087 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003088 sp<FakeWindowHandle> windowInSecondary;
3089};
3090
3091TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
3092 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3094 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3095 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003096 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08003097 windowInSecondary->assertNoEvents();
3098
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003099 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3101 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3102 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003103 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003104 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08003105}
3106
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003107TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08003108 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3110 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003111 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003112 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08003113 windowInSecondary->assertNoEvents();
3114
3115 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003117 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003118 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003119 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08003120
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003121 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003122 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08003123
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003124 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003125 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
3126 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08003127
3128 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003129 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003130 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08003131 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003132 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08003133 windowInSecondary->assertNoEvents();
3134}
3135
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003136// Test per-display input monitors for motion event.
3137TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08003138 FakeMonitorReceiver monitorInPrimary =
3139 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3140 FakeMonitorReceiver monitorInSecondary =
3141 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003142
3143 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3145 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3146 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003147 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003148 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003149 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003150 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003151
3152 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3154 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3155 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003156 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003157 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003158 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08003159 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003160
3161 // Test inject a non-pointer motion event.
3162 // If specific a display, it will dispatch to the focused window of particular display,
3163 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3165 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
3166 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003167 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003168 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003169 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003170 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003171}
3172
3173// Test per-display input monitors for key event.
3174TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003175 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08003176 FakeMonitorReceiver monitorInPrimary =
3177 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3178 FakeMonitorReceiver monitorInSecondary =
3179 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003180
3181 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3183 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003184 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003185 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003186 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003187 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003188}
3189
Vishnu Nair958da932020-08-21 17:12:37 -07003190TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
3191 sp<FakeWindowHandle> secondWindowInPrimary =
3192 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
3193 secondWindowInPrimary->setFocusable(true);
3194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
3195 setFocusedWindow(secondWindowInPrimary);
3196 windowInPrimary->consumeFocusEvent(false);
3197 secondWindowInPrimary->consumeFocusEvent(true);
3198
3199 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
3201 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003202 windowInPrimary->assertNoEvents();
3203 windowInSecondary->assertNoEvents();
3204 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3205}
3206
Jackal Guof9696682018-10-05 12:23:23 +08003207class InputFilterTest : public InputDispatcherTest {
3208protected:
Jackal Guof9696682018-10-05 12:23:23 +08003209 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered) {
3210 NotifyMotionArgs motionArgs;
3211
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003212 motionArgs =
3213 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003214 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003215 motionArgs =
3216 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003217 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003218 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003219 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003220 mFakePolicy->assertFilterInputEventWasCalled(motionArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003221 } else {
3222 mFakePolicy->assertFilterInputEventWasNotCalled();
3223 }
3224 }
3225
3226 void testNotifyKey(bool expectToBeFiltered) {
3227 NotifyKeyArgs keyArgs;
3228
3229 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3230 mDispatcher->notifyKey(&keyArgs);
3231 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
3232 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003233 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003234
3235 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003236 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003237 } else {
3238 mFakePolicy->assertFilterInputEventWasNotCalled();
3239 }
3240 }
3241};
3242
3243// Test InputFilter for MotionEvent
3244TEST_F(InputFilterTest, MotionEvent_InputFilter) {
3245 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
3246 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3247 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3248
3249 // Enable InputFilter
3250 mDispatcher->setInputFilterEnabled(true);
3251 // Test touch on both primary and second display, and check if both events are filtered.
3252 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
3253 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
3254
3255 // Disable InputFilter
3256 mDispatcher->setInputFilterEnabled(false);
3257 // Test touch on both primary and second display, and check if both events aren't filtered.
3258 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3259 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3260}
3261
3262// Test InputFilter for KeyEvent
3263TEST_F(InputFilterTest, KeyEvent_InputFilter) {
3264 // Since the InputFilter is disabled by default, check if key event aren't filtered.
3265 testNotifyKey(/*expectToBeFiltered*/ false);
3266
3267 // Enable InputFilter
3268 mDispatcher->setInputFilterEnabled(true);
3269 // Send a key event, and check if it is filtered.
3270 testNotifyKey(/*expectToBeFiltered*/ true);
3271
3272 // Disable InputFilter
3273 mDispatcher->setInputFilterEnabled(false);
3274 // Send a key event, and check if it isn't filtered.
3275 testNotifyKey(/*expectToBeFiltered*/ false);
3276}
3277
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003278class InputFilterInjectionPolicyTest : public InputDispatcherTest {
3279protected:
3280 virtual void SetUp() override {
3281 InputDispatcherTest::SetUp();
3282
3283 /**
3284 * We don't need to enable input filter to test the injected event policy, but we enabled it
3285 * here to make the tests more realistic, since this policy only matters when inputfilter is
3286 * on.
3287 */
3288 mDispatcher->setInputFilterEnabled(true);
3289
3290 std::shared_ptr<InputApplicationHandle> application =
3291 std::make_shared<FakeApplicationHandle>();
3292 mWindow =
3293 new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT);
3294
3295 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3296 mWindow->setFocusable(true);
3297 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3298 setFocusedWindow(mWindow);
3299 mWindow->consumeFocusEvent(true);
3300 }
3301
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003302 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3303 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003304 KeyEvent event;
3305
3306 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3307 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
3308 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
3309 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
3310 const int32_t additionalPolicyFlags =
3311 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
3312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3313 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3314 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3315 policyFlags | additionalPolicyFlags));
3316
3317 InputEvent* received = mWindow->consume();
3318 ASSERT_NE(nullptr, received);
3319 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003320 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
3321 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
3322 ASSERT_EQ(flags, keyEvent.getFlags());
3323 }
3324
3325 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3326 int32_t flags) {
3327 MotionEvent event;
3328 PointerProperties pointerProperties[1];
3329 PointerCoords pointerCoords[1];
3330 pointerProperties[0].clear();
3331 pointerProperties[0].id = 0;
3332 pointerCoords[0].clear();
3333 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
3334 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
3335
3336 ui::Transform identityTransform;
3337 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3338 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
3339 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
3340 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
3341 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Evan Rosky09576692021-07-01 12:22:09 -07003342 AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
3343 0 /*INVALID_DISPLAY_SIZE*/, 0 /*INVALID_DISPLAY_SIZE*/, eventTime,
3344 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003345 /*pointerCount*/ 1, pointerProperties, pointerCoords);
3346
3347 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
3348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3349 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3350 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3351 policyFlags | additionalPolicyFlags));
3352
3353 InputEvent* received = mWindow->consume();
3354 ASSERT_NE(nullptr, received);
3355 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
3356 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
3357 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
3358 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003359 }
3360
3361private:
3362 sp<FakeWindowHandle> mWindow;
3363};
3364
3365TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003366 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
3367 // filter. Without it, the event will no different from a regularly injected event, and the
3368 // injected device id will be overwritten.
3369 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3370 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003371}
3372
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003373TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003374 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003375 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3376 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3377}
3378
3379TEST_F(InputFilterInjectionPolicyTest,
3380 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
3381 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
3382 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3383 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003384}
3385
3386TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
3387 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003388 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003389}
3390
chaviwfd6d3512019-03-25 13:23:49 -07003391class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003392 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07003393 InputDispatcherTest::SetUp();
3394
Chris Yea209fde2020-07-22 13:54:51 -07003395 std::shared_ptr<FakeApplicationHandle> application =
3396 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003397 mUnfocusedWindow =
3398 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003399 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
3400 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3401 // window.
chaviw3277faf2021-05-19 16:45:23 -05003402 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003403
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003404 mFocusedWindow =
3405 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3406 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05003407 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
chaviwfd6d3512019-03-25 13:23:49 -07003408
3409 // Set focused application.
3410 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003411 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07003412
3413 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003414 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003415 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003416 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07003417 }
3418
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003419 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07003420 InputDispatcherTest::TearDown();
3421
3422 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003423 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07003424 }
3425
3426protected:
3427 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003428 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003429 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07003430};
3431
3432// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3433// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
3434// the onPointerDownOutsideFocus callback.
3435TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003437 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3438 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003439 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003440 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003441
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003442 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07003443 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
3444}
3445
3446// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
3447// DOWN on the window that doesn't have focus. Ensure no window received the
3448// onPointerDownOutsideFocus callback.
3449TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003451 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003453 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003454
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003455 ASSERT_TRUE(mDispatcher->waitForIdle());
3456 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003457}
3458
3459// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
3460// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
3461TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003462 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3463 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003464 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003465 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003466
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003467 ASSERT_TRUE(mDispatcher->waitForIdle());
3468 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003469}
3470
3471// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3472// DOWN on the window that already has focus. Ensure no window received the
3473// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003474TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003476 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003477 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07003479 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07003480
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003481 ASSERT_TRUE(mDispatcher->waitForIdle());
3482 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07003483}
3484
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08003485// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
3486// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
3487TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
3488 const MotionEvent event =
3489 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3490 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
3491 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
3492 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
3493 .build();
3494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
3495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3496 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
3497
3498 ASSERT_TRUE(mDispatcher->waitForIdle());
3499 mFakePolicy->assertOnPointerDownWasNotCalled();
3500 // Ensure that the unfocused window did not receive any FOCUS events.
3501 mUnfocusedWindow->assertNoEvents();
3502}
3503
chaviwaf87b3e2019-10-01 16:59:28 -07003504// These tests ensures we can send touch events to a single client when there are multiple input
3505// windows that point to the same client token.
3506class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
3507 virtual void SetUp() override {
3508 InputDispatcherTest::SetUp();
3509
Chris Yea209fde2020-07-22 13:54:51 -07003510 std::shared_ptr<FakeApplicationHandle> application =
3511 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07003512 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
3513 ADISPLAY_ID_DEFAULT);
3514 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
3515 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
chaviw3277faf2021-05-19 16:45:23 -05003516 mWindow1->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003517 mWindow1->setFrame(Rect(0, 0, 100, 100));
3518
3519 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
3520 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviw3277faf2021-05-19 16:45:23 -05003521 mWindow2->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
chaviwaf87b3e2019-10-01 16:59:28 -07003522 mWindow2->setFrame(Rect(100, 100, 200, 200));
3523
Arthur Hung72d8dc32020-03-28 00:48:39 +00003524 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07003525 }
3526
3527protected:
3528 sp<FakeWindowHandle> mWindow1;
3529 sp<FakeWindowHandle> mWindow2;
3530
3531 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05003532 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07003533 vec2 vals = windowInfo->transform.transform(point.x, point.y);
3534 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07003535 }
3536
3537 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
3538 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003539 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07003540 InputEvent* event = window->consume();
3541
3542 ASSERT_NE(nullptr, event) << name.c_str()
3543 << ": consumer should have returned non-NULL event.";
3544
3545 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
3546 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
3547 << " event, got " << inputEventTypeToString(event->getType()) << " event";
3548
3549 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
3550 EXPECT_EQ(expectedAction, motionEvent.getAction());
3551
3552 for (size_t i = 0; i < points.size(); i++) {
3553 float expectedX = points[i].x;
3554 float expectedY = points[i].y;
3555
3556 EXPECT_EQ(expectedX, motionEvent.getX(i))
3557 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
3558 << ", got " << motionEvent.getX(i);
3559 EXPECT_EQ(expectedY, motionEvent.getY(i))
3560 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
3561 << ", got " << motionEvent.getY(i);
3562 }
3563 }
chaviw9eaa22c2020-07-01 16:21:27 -07003564
3565 void touchAndAssertPositions(int32_t action, std::vector<PointF> touchedPoints,
3566 std::vector<PointF> expectedPoints) {
3567 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
3568 ADISPLAY_ID_DEFAULT, touchedPoints);
3569 mDispatcher->notifyMotion(&motionArgs);
3570
3571 // Always consume from window1 since it's the window that has the InputReceiver
3572 consumeMotionEvent(mWindow1, action, expectedPoints);
3573 }
chaviwaf87b3e2019-10-01 16:59:28 -07003574};
3575
3576TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
3577 // Touch Window 1
3578 PointF touchedPoint = {10, 10};
3579 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003580 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003581
3582 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003583 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003584
3585 // Touch Window 2
3586 touchedPoint = {150, 150};
3587 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003588 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003589}
3590
chaviw9eaa22c2020-07-01 16:21:27 -07003591TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
3592 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07003593 mWindow2->setWindowScale(0.5f, 0.5f);
3594
3595 // Touch Window 1
3596 PointF touchedPoint = {10, 10};
3597 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003598 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003599 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07003600 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003601
3602 // Touch Window 2
3603 touchedPoint = {150, 150};
3604 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07003605 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
3606 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003607
chaviw9eaa22c2020-07-01 16:21:27 -07003608 // Update the transform so rotation is set
3609 mWindow2->setWindowTransform(0, -1, 1, 0);
3610 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
3611 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07003612}
3613
chaviw9eaa22c2020-07-01 16:21:27 -07003614TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003615 mWindow2->setWindowScale(0.5f, 0.5f);
3616
3617 // Touch Window 1
3618 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3619 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003620 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003621
3622 // Touch Window 2
3623 int32_t actionPointerDown =
3624 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003625 touchedPoints.push_back(PointF{150, 150});
3626 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3627 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003628
chaviw9eaa22c2020-07-01 16:21:27 -07003629 // Release Window 2
3630 int32_t actionPointerUp =
3631 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3632 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3633 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003634
chaviw9eaa22c2020-07-01 16:21:27 -07003635 // Update the transform so rotation is set for Window 2
3636 mWindow2->setWindowTransform(0, -1, 1, 0);
3637 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3638 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003639}
3640
chaviw9eaa22c2020-07-01 16:21:27 -07003641TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003642 mWindow2->setWindowScale(0.5f, 0.5f);
3643
3644 // Touch Window 1
3645 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3646 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003647 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003648
3649 // Touch Window 2
3650 int32_t actionPointerDown =
3651 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003652 touchedPoints.push_back(PointF{150, 150});
3653 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003654
chaviw9eaa22c2020-07-01 16:21:27 -07003655 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003656
3657 // Move both windows
3658 touchedPoints = {{20, 20}, {175, 175}};
3659 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3660 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3661
chaviw9eaa22c2020-07-01 16:21:27 -07003662 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003663
chaviw9eaa22c2020-07-01 16:21:27 -07003664 // Release Window 2
3665 int32_t actionPointerUp =
3666 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3667 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
3668 expectedPoints.pop_back();
3669
3670 // Touch Window 2
3671 mWindow2->setWindowTransform(0, -1, 1, 0);
3672 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
3673 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
3674
3675 // Move both windows
3676 touchedPoints = {{20, 20}, {175, 175}};
3677 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3678 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3679
3680 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003681}
3682
3683TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
3684 mWindow1->setWindowScale(0.5f, 0.5f);
3685
3686 // Touch Window 1
3687 std::vector<PointF> touchedPoints = {PointF{10, 10}};
3688 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07003689 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003690
3691 // Touch Window 2
3692 int32_t actionPointerDown =
3693 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07003694 touchedPoints.push_back(PointF{150, 150});
3695 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003696
chaviw9eaa22c2020-07-01 16:21:27 -07003697 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003698
3699 // Move both windows
3700 touchedPoints = {{20, 20}, {175, 175}};
3701 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
3702 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
3703
chaviw9eaa22c2020-07-01 16:21:27 -07003704 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00003705}
3706
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003707class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
3708 virtual void SetUp() override {
3709 InputDispatcherTest::SetUp();
3710
Chris Yea209fde2020-07-22 13:54:51 -07003711 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003712 mApplication->setDispatchingTimeout(20ms);
3713 mWindow =
3714 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3715 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05003716 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07003717 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003718 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
3719 // window.
chaviw3277faf2021-05-19 16:45:23 -05003720 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003721
3722 // Set focused application.
3723 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
3724
3725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003726 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003727 mWindow->consumeFocusEvent(true);
3728 }
3729
3730 virtual void TearDown() override {
3731 InputDispatcherTest::TearDown();
3732 mWindow.clear();
3733 }
3734
3735protected:
Chris Yea209fde2020-07-22 13:54:51 -07003736 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003737 sp<FakeWindowHandle> mWindow;
3738 static constexpr PointF WINDOW_LOCATION = {20, 20};
3739
3740 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003742 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3743 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003745 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3746 WINDOW_LOCATION));
3747 }
3748};
3749
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003750// Send a tap and respond, which should not cause an ANR.
3751TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
3752 tapOnWindow();
3753 mWindow->consumeMotionDown();
3754 mWindow->consumeMotionUp();
3755 ASSERT_TRUE(mDispatcher->waitForIdle());
3756 mFakePolicy->assertNotifyAnrWasNotCalled();
3757}
3758
3759// Send a regular key and respond, which should not cause an ANR.
3760TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003762 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
3763 ASSERT_TRUE(mDispatcher->waitForIdle());
3764 mFakePolicy->assertNotifyAnrWasNotCalled();
3765}
3766
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003767TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
3768 mWindow->setFocusable(false);
3769 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3770 mWindow->consumeFocusEvent(false);
3771
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003772 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003773 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003774 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
3775 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05003777 // Key will not go to window because we have no focused window.
3778 // The 'no focused window' ANR timer should start instead.
3779
3780 // Now, the focused application goes away.
3781 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
3782 // The key should get dropped and there should be no ANR.
3783
3784 ASSERT_TRUE(mDispatcher->waitForIdle());
3785 mFakePolicy->assertNotifyAnrWasNotCalled();
3786}
3787
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003788// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003789// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
3790// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003791TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003793 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3794 WINDOW_LOCATION));
3795
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003796 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
3797 ASSERT_TRUE(sequenceNum);
3798 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003799 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003800
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003801 mWindow->finishEvent(*sequenceNum);
3802 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
3803 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003804 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003805 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003806}
3807
3808// Send a key to the app and have the app not respond right away.
3809TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
3810 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003812 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
3813 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003814 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003815 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003816 ASSERT_TRUE(mDispatcher->waitForIdle());
3817}
3818
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003819// We have a focused application, but no focused window
3820TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003821 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003822 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3823 mWindow->consumeFocusEvent(false);
3824
3825 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003827 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3828 WINDOW_LOCATION));
3829 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
3830 mDispatcher->waitForIdle();
3831 mFakePolicy->assertNotifyAnrWasNotCalled();
3832
3833 // Once a focused event arrives, we get an ANR for this application
3834 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3835 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003836 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003837 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003838 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003839 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003840 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003841 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003842 ASSERT_TRUE(mDispatcher->waitForIdle());
3843}
3844
3845// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003846// Make sure that we don't notify policy twice about the same ANR.
3847TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003848 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003849 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3850 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003851
3852 // Once a focused event arrives, we get an ANR for this application
3853 // We specify the injection timeout to be smaller than the application timeout, to ensure that
3854 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003855 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003856 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003857 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003858 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003859 const std::chrono::duration appTimeout =
3860 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003861 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003862
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003863 std::this_thread::sleep_for(appTimeout);
3864 // ANR should not be raised again. It is up to policy to do that if it desires.
3865 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003866
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003867 // If we now get a focused window, the ANR should stop, but the policy handles that via
3868 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003869 ASSERT_TRUE(mDispatcher->waitForIdle());
3870}
3871
3872// We have a focused application, but no focused window
3873TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07003874 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003875 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3876 mWindow->consumeFocusEvent(false);
3877
3878 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003879 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003880 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003881 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
3882 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003883
3884 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05003885 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003886
3887 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003888 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003889 ASSERT_TRUE(mDispatcher->waitForIdle());
3890 mWindow->assertNoEvents();
3891}
3892
3893/**
3894 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
3895 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
3896 * If we process 1 of the events, but ANR on the second event with the same timestamp,
3897 * the ANR mechanism should still work.
3898 *
3899 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
3900 * DOWN event, while not responding on the second one.
3901 */
3902TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
3903 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
3904 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3905 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3906 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3907 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003908 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003909
3910 // Now send ACTION_UP, with identical timestamp
3911 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3912 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
3913 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
3914 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003915 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003916
3917 // We have now sent down and up. Let's consume first event and then ANR on the second.
3918 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3919 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003920 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003921}
3922
3923// If an app is not responding to a key event, gesture monitors should continue to receive
3924// new motion events
3925TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnKey) {
3926 FakeMonitorReceiver monitor =
3927 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3928 true /*isGestureMonitor*/);
3929
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3931 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003932 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003934
3935 // Stuck on the ACTION_UP
3936 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003937 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003938
3939 // New tap will go to the gesture monitor, but not to the window
3940 tapOnWindow();
3941 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3942 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3943
3944 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3945 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003946 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003947 mWindow->assertNoEvents();
3948 monitor.assertNoEvents();
3949}
3950
3951// If an app is not responding to a motion event, gesture monitors should continue to receive
3952// new motion events
3953TEST_F(InputDispatcherSingleWindowAnr, GestureMonitors_ReceiveEventsDuringAppAnrOnMotion) {
3954 FakeMonitorReceiver monitor =
3955 FakeMonitorReceiver(mDispatcher, "Gesture monitor", ADISPLAY_ID_DEFAULT,
3956 true /*isGestureMonitor*/);
3957
3958 tapOnWindow();
3959 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3960 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3961
3962 mWindow->consumeMotionDown();
3963 // Stuck on the ACTION_UP
3964 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003965 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003966
3967 // New tap will go to the gesture monitor, but not to the window
3968 tapOnWindow();
3969 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3970 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
3971
3972 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
3973 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003974 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003975 mWindow->assertNoEvents();
3976 monitor.assertNoEvents();
3977}
3978
3979// If a window is unresponsive, then you get anr. if the window later catches up and starts to
3980// process events, you don't get an anr. When the window later becomes unresponsive again, you
3981// get an ANR again.
3982// 1. tap -> block on ACTION_UP -> receive ANR
3983// 2. consume all pending events (= queue becomes healthy again)
3984// 3. tap again -> block on ACTION_UP again -> receive ANR second time
3985TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
3986 tapOnWindow();
3987
3988 mWindow->consumeMotionDown();
3989 // Block on ACTION_UP
3990 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003991 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003992 mWindow->consumeMotionUp(); // Now the connection should be healthy again
3993 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003994 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003995 mWindow->assertNoEvents();
3996
3997 tapOnWindow();
3998 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00003999 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004000 mWindow->consumeMotionUp();
4001
4002 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004003 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004004 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004005 mWindow->assertNoEvents();
4006}
4007
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004008// If a connection remains unresponsive for a while, make sure policy is only notified once about
4009// it.
4010TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004012 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4013 WINDOW_LOCATION));
4014
4015 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004016 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004017 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004018 // 'notifyConnectionUnresponsive' should only be called once per connection
4019 mFakePolicy->assertNotifyAnrWasNotCalled();
4020 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004021 mWindow->consumeMotionDown();
4022 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4023 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4024 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004025 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004026 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004027 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004028}
4029
4030/**
4031 * If a window is processing a motion event, and then a key event comes in, the key event should
4032 * not to to the focused window until the motion is processed.
4033 *
4034 * Warning!!!
4035 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4036 * and the injection timeout that we specify when injecting the key.
4037 * We must have the injection timeout (10ms) be smaller than
4038 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4039 *
4040 * If that value changes, this test should also change.
4041 */
4042TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
4043 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4044 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4045
4046 tapOnWindow();
4047 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4048 ASSERT_TRUE(downSequenceNum);
4049 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4050 ASSERT_TRUE(upSequenceNum);
4051 // Don't finish the events yet, and send a key
4052 // Injection will "succeed" because we will eventually give up and send the key to the focused
4053 // window even if motions are still being processed. But because the injection timeout is short,
4054 // we will receive INJECTION_TIMED_OUT as the result.
4055
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004056 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004057 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004058 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4059 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004060 // Key will not be sent to the window, yet, because the window is still processing events
4061 // and the key remains pending, waiting for the touch events to be processed
4062 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4063 ASSERT_FALSE(keySequenceNum);
4064
4065 std::this_thread::sleep_for(500ms);
4066 // if we wait long enough though, dispatcher will give up, and still send the key
4067 // to the focused window, even though we have not yet finished the motion event
4068 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4069 mWindow->finishEvent(*downSequenceNum);
4070 mWindow->finishEvent(*upSequenceNum);
4071}
4072
4073/**
4074 * If a window is processing a motion event, and then a key event comes in, the key event should
4075 * not go to the focused window until the motion is processed.
4076 * If then a new motion comes in, then the pending key event should be going to the currently
4077 * focused window right away.
4078 */
4079TEST_F(InputDispatcherSingleWindowAnr,
4080 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
4081 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4082 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4083
4084 tapOnWindow();
4085 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4086 ASSERT_TRUE(downSequenceNum);
4087 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4088 ASSERT_TRUE(upSequenceNum);
4089 // Don't finish the events yet, and send a key
4090 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004092 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004093 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004094 // At this point, key is still pending, and should not be sent to the application yet.
4095 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4096 ASSERT_FALSE(keySequenceNum);
4097
4098 // Now tap down again. It should cause the pending key to go to the focused window right away.
4099 tapOnWindow();
4100 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
4101 // the other events yet. We can finish events in any order.
4102 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
4103 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
4104 mWindow->consumeMotionDown();
4105 mWindow->consumeMotionUp();
4106 mWindow->assertNoEvents();
4107}
4108
4109class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
4110 virtual void SetUp() override {
4111 InputDispatcherTest::SetUp();
4112
Chris Yea209fde2020-07-22 13:54:51 -07004113 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004114 mApplication->setDispatchingTimeout(10ms);
4115 mUnfocusedWindow =
4116 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
4117 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
4118 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4119 // window.
4120 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
chaviw3277faf2021-05-19 16:45:23 -05004121 mUnfocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL |
4122 WindowInfo::Flag::WATCH_OUTSIDE_TOUCH |
4123 WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004124
4125 mFocusedWindow =
4126 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004127 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004128 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05004129 mFocusedWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL | WindowInfo::Flag::SPLIT_TOUCH);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004130
4131 // Set focused application.
4132 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07004133 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004134
4135 // Expect one focus window exist in display.
4136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004137 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004138 mFocusedWindow->consumeFocusEvent(true);
4139 }
4140
4141 virtual void TearDown() override {
4142 InputDispatcherTest::TearDown();
4143
4144 mUnfocusedWindow.clear();
4145 mFocusedWindow.clear();
4146 }
4147
4148protected:
Chris Yea209fde2020-07-22 13:54:51 -07004149 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004150 sp<FakeWindowHandle> mUnfocusedWindow;
4151 sp<FakeWindowHandle> mFocusedWindow;
4152 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
4153 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
4154 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
4155
4156 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
4157
4158 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
4159
4160private:
4161 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004163 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4164 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004166 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4167 location));
4168 }
4169};
4170
4171// If we have 2 windows that are both unresponsive, the one with the shortest timeout
4172// should be ANR'd first.
4173TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004175 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4176 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004178 mFocusedWindow->consumeMotionDown();
4179 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4180 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4181 // We consumed all events, so no ANR
4182 ASSERT_TRUE(mDispatcher->waitForIdle());
4183 mFakePolicy->assertNotifyAnrWasNotCalled();
4184
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004186 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4187 FOCUSED_WINDOW_LOCATION));
4188 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
4189 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004190
4191 const std::chrono::duration timeout =
4192 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004193 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004194 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
4195 // sequence to make it consistent
4196 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004197 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004198 mFocusedWindow->consumeMotionDown();
4199 // This cancel is generated because the connection was unresponsive
4200 mFocusedWindow->consumeMotionCancel();
4201 mFocusedWindow->assertNoEvents();
4202 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004203 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004204 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004205 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004206}
4207
4208// If we have 2 windows with identical timeouts that are both unresponsive,
4209// it doesn't matter which order they should have ANR.
4210// But we should receive ANR for both.
4211TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
4212 // Set the timeout for unfocused window to match the focused window
4213 mUnfocusedWindow->setDispatchingTimeout(10ms);
4214 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4215
4216 tapOnFocusedWindow();
4217 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004218 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
4219 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004220
4221 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004222 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
4223 mFocusedWindow->getToken() == anrConnectionToken2);
4224 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
4225 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004226
4227 ASSERT_TRUE(mDispatcher->waitForIdle());
4228 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004229
4230 mFocusedWindow->consumeMotionDown();
4231 mFocusedWindow->consumeMotionUp();
4232 mUnfocusedWindow->consumeMotionOutside();
4233
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004234 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
4235 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004236
4237 // Both applications should be marked as responsive, in any order
4238 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
4239 mFocusedWindow->getToken() == responsiveToken2);
4240 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
4241 mUnfocusedWindow->getToken() == responsiveToken2);
4242 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004243}
4244
4245// If a window is already not responding, the second tap on the same window should be ignored.
4246// We should also log an error to account for the dropped event (not tested here).
4247// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
4248TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
4249 tapOnFocusedWindow();
4250 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4251 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4252 // Receive the events, but don't respond
4253 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
4254 ASSERT_TRUE(downEventSequenceNum);
4255 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
4256 ASSERT_TRUE(upEventSequenceNum);
4257 const std::chrono::duration timeout =
4258 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004259 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004260
4261 // Tap once again
4262 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004263 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004264 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4265 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004266 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004267 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4268 FOCUSED_WINDOW_LOCATION));
4269 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
4270 // valid touch target
4271 mUnfocusedWindow->assertNoEvents();
4272
4273 // Consume the first tap
4274 mFocusedWindow->finishEvent(*downEventSequenceNum);
4275 mFocusedWindow->finishEvent(*upEventSequenceNum);
4276 ASSERT_TRUE(mDispatcher->waitForIdle());
4277 // The second tap did not go to the focused window
4278 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004279 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004280 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004281 mFakePolicy->assertNotifyAnrWasNotCalled();
4282}
4283
4284// If you tap outside of all windows, there will not be ANR
4285TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004286 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004287 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4288 LOCATION_OUTSIDE_ALL_WINDOWS));
4289 ASSERT_TRUE(mDispatcher->waitForIdle());
4290 mFakePolicy->assertNotifyAnrWasNotCalled();
4291}
4292
4293// Since the focused window is paused, tapping on it should not produce any events
4294TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
4295 mFocusedWindow->setPaused(true);
4296 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4297
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004298 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004299 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4300 FOCUSED_WINDOW_LOCATION));
4301
4302 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
4303 ASSERT_TRUE(mDispatcher->waitForIdle());
4304 // Should not ANR because the window is paused, and touches shouldn't go to it
4305 mFakePolicy->assertNotifyAnrWasNotCalled();
4306
4307 mFocusedWindow->assertNoEvents();
4308 mUnfocusedWindow->assertNoEvents();
4309}
4310
4311/**
4312 * If a window is processing a motion event, and then a key event comes in, the key event should
4313 * not to to the focused window until the motion is processed.
4314 * If a different window becomes focused at this time, the key should go to that window instead.
4315 *
4316 * Warning!!!
4317 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4318 * and the injection timeout that we specify when injecting the key.
4319 * We must have the injection timeout (10ms) be smaller than
4320 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4321 *
4322 * If that value changes, this test should also change.
4323 */
4324TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
4325 // Set a long ANR timeout to prevent it from triggering
4326 mFocusedWindow->setDispatchingTimeout(2s);
4327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4328
4329 tapOnUnfocusedWindow();
4330 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
4331 ASSERT_TRUE(downSequenceNum);
4332 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->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.
4337
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004338 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004339 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004340 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
4341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004342 // Key will not be sent to the window, yet, because the window is still processing events
4343 // and the key remains pending, waiting for the touch events to be processed
4344 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
4345 ASSERT_FALSE(keySequenceNum);
4346
4347 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07004348 mFocusedWindow->setFocusable(false);
4349 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004350 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004351 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004352
4353 // Focus events should precede the key events
4354 mUnfocusedWindow->consumeFocusEvent(true);
4355 mFocusedWindow->consumeFocusEvent(false);
4356
4357 // Finish the tap events, which should unblock dispatcher
4358 mUnfocusedWindow->finishEvent(*downSequenceNum);
4359 mUnfocusedWindow->finishEvent(*upSequenceNum);
4360
4361 // Now that all queues are cleared and no backlog in the connections, the key event
4362 // can finally go to the newly focused "mUnfocusedWindow".
4363 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4364 mFocusedWindow->assertNoEvents();
4365 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004366 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004367}
4368
4369// When the touch stream is split across 2 windows, and one of them does not respond,
4370// then ANR should be raised and the touch should be canceled for the unresponsive window.
4371// The other window should not be affected by that.
4372TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
4373 // Touch Window 1
4374 NotifyMotionArgs motionArgs =
4375 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4376 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
4377 mDispatcher->notifyMotion(&motionArgs);
4378 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4379 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4380
4381 // Touch Window 2
4382 int32_t actionPointerDown =
4383 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4384
4385 motionArgs =
4386 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4387 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
4388 mDispatcher->notifyMotion(&motionArgs);
4389
4390 const std::chrono::duration timeout =
4391 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004392 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004393
4394 mUnfocusedWindow->consumeMotionDown();
4395 mFocusedWindow->consumeMotionDown();
4396 // Focused window may or may not receive ACTION_MOVE
4397 // But it should definitely receive ACTION_CANCEL due to the ANR
4398 InputEvent* event;
4399 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
4400 ASSERT_TRUE(moveOrCancelSequenceNum);
4401 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
4402 ASSERT_NE(nullptr, event);
4403 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
4404 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
4405 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
4406 mFocusedWindow->consumeMotionCancel();
4407 } else {
4408 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
4409 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004410 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004411 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004412
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004413 mUnfocusedWindow->assertNoEvents();
4414 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004415 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004416}
4417
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004418/**
4419 * If we have no focused window, and a key comes in, we start the ANR timer.
4420 * The focused application should add a focused window before the timer runs out to prevent ANR.
4421 *
4422 * If the user touches another application during this time, the key should be dropped.
4423 * Next, if a new focused window comes in, without toggling the focused application,
4424 * then no ANR should occur.
4425 *
4426 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
4427 * but in some cases the policy may not update the focused application.
4428 */
4429TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
4430 std::shared_ptr<FakeApplicationHandle> focusedApplication =
4431 std::make_shared<FakeApplicationHandle>();
4432 focusedApplication->setDispatchingTimeout(60ms);
4433 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
4434 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
4435 mFocusedWindow->setFocusable(false);
4436
4437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4438 mFocusedWindow->consumeFocusEvent(false);
4439
4440 // Send a key. The ANR timer should start because there is no focused window.
4441 // 'focusedApplication' will get blamed if this timer completes.
4442 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004443 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004444 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004445 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4446 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05004448
4449 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
4450 // then the injected touches won't cause the focused event to get dropped.
4451 // The dispatcher only checks for whether the queue should be pruned upon queueing.
4452 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
4453 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
4454 // For this test, it means that the key would get delivered to the window once it becomes
4455 // focused.
4456 std::this_thread::sleep_for(10ms);
4457
4458 // Touch unfocused window. This should force the pending key to get dropped.
4459 NotifyMotionArgs motionArgs =
4460 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4461 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
4462 mDispatcher->notifyMotion(&motionArgs);
4463
4464 // We do not consume the motion right away, because that would require dispatcher to first
4465 // process (== drop) the key event, and by that time, ANR will be raised.
4466 // Set the focused window first.
4467 mFocusedWindow->setFocusable(true);
4468 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4469 setFocusedWindow(mFocusedWindow);
4470 mFocusedWindow->consumeFocusEvent(true);
4471 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
4472 // to another application. This could be a bug / behaviour in the policy.
4473
4474 mUnfocusedWindow->consumeMotionDown();
4475
4476 ASSERT_TRUE(mDispatcher->waitForIdle());
4477 // Should not ANR because we actually have a focused window. It was just added too slowly.
4478 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
4479}
4480
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004481// These tests ensure we cannot send touch events to a window that's positioned behind a window
4482// that has feature NO_INPUT_CHANNEL.
4483// Layout:
4484// Top (closest to user)
4485// mNoInputWindow (above all windows)
4486// mBottomWindow
4487// Bottom (furthest from user)
4488class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
4489 virtual void SetUp() override {
4490 InputDispatcherTest::SetUp();
4491
4492 mApplication = std::make_shared<FakeApplicationHandle>();
4493 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4494 "Window without input channel", ADISPLAY_ID_DEFAULT,
4495 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
4496
chaviw3277faf2021-05-19 16:45:23 -05004497 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004498 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4499 // It's perfectly valid for this window to not have an associated input channel
4500
4501 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
4502 ADISPLAY_ID_DEFAULT);
4503 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
4504
4505 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4506 }
4507
4508protected:
4509 std::shared_ptr<FakeApplicationHandle> mApplication;
4510 sp<FakeWindowHandle> mNoInputWindow;
4511 sp<FakeWindowHandle> mBottomWindow;
4512};
4513
4514TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
4515 PointF touchedPoint = {10, 10};
4516
4517 NotifyMotionArgs motionArgs =
4518 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4519 ADISPLAY_ID_DEFAULT, {touchedPoint});
4520 mDispatcher->notifyMotion(&motionArgs);
4521
4522 mNoInputWindow->assertNoEvents();
4523 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
4524 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
4525 // and therefore should prevent mBottomWindow from receiving touches
4526 mBottomWindow->assertNoEvents();
4527}
4528
4529/**
4530 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
4531 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
4532 */
4533TEST_F(InputDispatcherMultiWindowOcclusionTests,
4534 NoInputChannelFeature_DropsTouchesWithValidChannel) {
4535 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
4536 "Window with input channel and NO_INPUT_CHANNEL",
4537 ADISPLAY_ID_DEFAULT);
4538
chaviw3277faf2021-05-19 16:45:23 -05004539 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05004540 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
4541 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
4542
4543 PointF touchedPoint = {10, 10};
4544
4545 NotifyMotionArgs motionArgs =
4546 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4547 ADISPLAY_ID_DEFAULT, {touchedPoint});
4548 mDispatcher->notifyMotion(&motionArgs);
4549
4550 mNoInputWindow->assertNoEvents();
4551 mBottomWindow->assertNoEvents();
4552}
4553
Vishnu Nair958da932020-08-21 17:12:37 -07004554class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
4555protected:
4556 std::shared_ptr<FakeApplicationHandle> mApp;
4557 sp<FakeWindowHandle> mWindow;
4558 sp<FakeWindowHandle> mMirror;
4559
4560 virtual void SetUp() override {
4561 InputDispatcherTest::SetUp();
4562 mApp = std::make_shared<FakeApplicationHandle>();
4563 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4564 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
4565 mWindow->getToken());
4566 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4567 mWindow->setFocusable(true);
4568 mMirror->setFocusable(true);
4569 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4570 }
4571};
4572
4573TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
4574 // Request focus on a mirrored window
4575 setFocusedWindow(mMirror);
4576
4577 // window gets focused
4578 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4580 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004581 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4582}
4583
4584// A focused & mirrored window remains focused only if the window and its mirror are both
4585// focusable.
4586TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
4587 setFocusedWindow(mMirror);
4588
4589 // window gets focused
4590 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4592 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004593 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4595 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004596 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4597
4598 mMirror->setFocusable(false);
4599 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4600
4601 // window loses focus since one of the windows associated with the token in not focusable
4602 mWindow->consumeFocusEvent(false);
4603
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004604 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4605 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004606 mWindow->assertNoEvents();
4607}
4608
4609// A focused & mirrored window remains focused until the window and its mirror both become
4610// invisible.
4611TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
4612 setFocusedWindow(mMirror);
4613
4614 // window gets focused
4615 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4617 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004618 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4620 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004621 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4622
4623 mMirror->setVisible(false);
4624 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4625
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4627 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004628 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4630 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004631 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4632
4633 mWindow->setVisible(false);
4634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4635
4636 // window loses focus only after all windows associated with the token become invisible.
4637 mWindow->consumeFocusEvent(false);
4638
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004639 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4640 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004641 mWindow->assertNoEvents();
4642}
4643
4644// A focused & mirrored window remains focused until both windows are removed.
4645TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
4646 setFocusedWindow(mMirror);
4647
4648 // window gets focused
4649 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4651 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004652 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4654 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004655 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4656
4657 // single window is removed but the window token remains focused
4658 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
4659
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4661 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004662 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
4664 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004665 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
4666
4667 // Both windows are removed
4668 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4669 mWindow->consumeFocusEvent(false);
4670
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004671 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4672 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004673 mWindow->assertNoEvents();
4674}
4675
4676// Focus request can be pending until one window becomes visible.
4677TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
4678 // Request focus on an invisible mirror.
4679 mWindow->setVisible(false);
4680 mMirror->setVisible(false);
4681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4682 setFocusedWindow(mMirror);
4683
4684 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07004686 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004687 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07004688
4689 mMirror->setVisible(true);
4690 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
4691
4692 // window gets focused
4693 mWindow->consumeFocusEvent(true);
4694 // window gets the pending key event
4695 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4696}
Prabir Pradhan99987712020-11-10 18:43:05 -08004697
4698class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
4699protected:
4700 std::shared_ptr<FakeApplicationHandle> mApp;
4701 sp<FakeWindowHandle> mWindow;
4702 sp<FakeWindowHandle> mSecondWindow;
4703
4704 void SetUp() override {
4705 InputDispatcherTest::SetUp();
4706 mApp = std::make_shared<FakeApplicationHandle>();
4707 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4708 mWindow->setFocusable(true);
4709 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
4710 mSecondWindow->setFocusable(true);
4711
4712 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
4713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
4714
4715 setFocusedWindow(mWindow);
4716 mWindow->consumeFocusEvent(true);
4717 }
4718
4719 void notifyPointerCaptureChanged(bool enabled) {
4720 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(enabled);
4721 mDispatcher->notifyPointerCaptureChanged(&args);
4722 }
4723
4724 void requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window, bool enabled) {
4725 mDispatcher->requestPointerCapture(window->getToken(), enabled);
4726 mFakePolicy->waitForSetPointerCapture(enabled);
4727 notifyPointerCaptureChanged(enabled);
4728 window->consumeCaptureEvent(enabled);
4729 }
4730};
4731
4732TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
4733 // Ensure that capture cannot be obtained for unfocused windows.
4734 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
4735 mFakePolicy->assertSetPointerCaptureNotCalled();
4736 mSecondWindow->assertNoEvents();
4737
4738 // Ensure that capture can be enabled from the focus window.
4739 requestAndVerifyPointerCapture(mWindow, true);
4740
4741 // Ensure that capture cannot be disabled from a window that does not have capture.
4742 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
4743 mFakePolicy->assertSetPointerCaptureNotCalled();
4744
4745 // Ensure that capture can be disabled from the window with capture.
4746 requestAndVerifyPointerCapture(mWindow, false);
4747}
4748
4749TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
4750 requestAndVerifyPointerCapture(mWindow, true);
4751
4752 setFocusedWindow(mSecondWindow);
4753
4754 // Ensure that the capture disabled event was sent first.
4755 mWindow->consumeCaptureEvent(false);
4756 mWindow->consumeFocusEvent(false);
4757 mSecondWindow->consumeFocusEvent(true);
4758 mFakePolicy->waitForSetPointerCapture(false);
4759
4760 // Ensure that additional state changes from InputReader are not sent to the window.
4761 notifyPointerCaptureChanged(false);
4762 notifyPointerCaptureChanged(true);
4763 notifyPointerCaptureChanged(false);
4764 mWindow->assertNoEvents();
4765 mSecondWindow->assertNoEvents();
4766 mFakePolicy->assertSetPointerCaptureNotCalled();
4767}
4768
4769TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
4770 requestAndVerifyPointerCapture(mWindow, true);
4771
4772 // InputReader unexpectedly disables and enables pointer capture.
4773 notifyPointerCaptureChanged(false);
4774 notifyPointerCaptureChanged(true);
4775
4776 // Ensure that Pointer Capture is disabled.
Prabir Pradhan7d030382020-12-21 07:58:35 -08004777 mFakePolicy->waitForSetPointerCapture(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08004778 mWindow->consumeCaptureEvent(false);
4779 mWindow->assertNoEvents();
4780}
4781
Prabir Pradhan167e6d92021-02-04 16:18:17 -08004782TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
4783 requestAndVerifyPointerCapture(mWindow, true);
4784
4785 // The first window loses focus.
4786 setFocusedWindow(mSecondWindow);
4787 mFakePolicy->waitForSetPointerCapture(false);
4788 mWindow->consumeCaptureEvent(false);
4789
4790 // Request Pointer Capture from the second window before the notification from InputReader
4791 // arrives.
4792 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
4793 mFakePolicy->waitForSetPointerCapture(true);
4794
4795 // InputReader notifies Pointer Capture was disabled (because of the focus change).
4796 notifyPointerCaptureChanged(false);
4797
4798 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
4799 notifyPointerCaptureChanged(true);
4800
4801 mSecondWindow->consumeFocusEvent(true);
4802 mSecondWindow->consumeCaptureEvent(true);
4803}
4804
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004805class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
4806protected:
4807 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00004808
4809 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
4810 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
4811
4812 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
4813 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
4814
4815 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
4816 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
4817 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
4818 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
4819 MAXIMUM_OBSCURING_OPACITY);
4820
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004821 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004822 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004823 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004824
4825 sp<FakeWindowHandle> mTouchWindow;
4826
4827 virtual void SetUp() override {
4828 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004829 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004830 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
4831 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
4832 }
4833
4834 virtual void TearDown() override {
4835 InputDispatcherTest::TearDown();
4836 mTouchWindow.clear();
4837 }
4838
chaviw3277faf2021-05-19 16:45:23 -05004839 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
4840 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004841 sp<FakeWindowHandle> window = getWindow(uid, name);
chaviw3277faf2021-05-19 16:45:23 -05004842 window->setFlags(WindowInfo::Flag::NOT_TOUCHABLE);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004843 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004844 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004845 return window;
4846 }
4847
4848 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
4849 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
4850 sp<FakeWindowHandle> window =
4851 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
4852 // Generate an arbitrary PID based on the UID
4853 window->setOwnerInfo(1777 + (uid % 10000), uid);
4854 return window;
4855 }
4856
4857 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
4858 NotifyMotionArgs args =
4859 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4860 ADISPLAY_ID_DEFAULT, points);
4861 mDispatcher->notifyMotion(&args);
4862 }
4863};
4864
4865TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004866 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004867 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004868 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004869
4870 touch();
4871
4872 mTouchWindow->assertNoEvents();
4873}
4874
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00004875TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00004876 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
4877 const sp<FakeWindowHandle>& w =
4878 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
4879 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4880
4881 touch();
4882
4883 mTouchWindow->assertNoEvents();
4884}
4885
4886TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00004887 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
4888 const sp<FakeWindowHandle>& w =
4889 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
4890 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4891
4892 touch();
4893
4894 w->assertNoEvents();
4895}
4896
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004897TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004898 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
4899 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004900
4901 touch();
4902
4903 mTouchWindow->consumeAnyMotionDown();
4904}
4905
4906TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004907 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004908 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004909 w->setFrame(Rect(0, 0, 50, 50));
4910 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004911
4912 touch({PointF{100, 100}});
4913
4914 mTouchWindow->consumeAnyMotionDown();
4915}
4916
4917TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004918 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00004919 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004920 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4921
4922 touch();
4923
4924 mTouchWindow->consumeAnyMotionDown();
4925}
4926
4927TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
4928 const sp<FakeWindowHandle>& w =
4929 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
4930 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004931
4932 touch();
4933
4934 mTouchWindow->consumeAnyMotionDown();
4935}
4936
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00004937TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
4938 const sp<FakeWindowHandle>& w =
4939 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
4940 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4941
4942 touch();
4943
4944 w->assertNoEvents();
4945}
4946
4947/**
4948 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
4949 * inside) while letting them pass-through. Note that even though touch passes through the occluding
4950 * window, the occluding window will still receive ACTION_OUTSIDE event.
4951 */
4952TEST_F(InputDispatcherUntrustedTouchesTest,
4953 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
4954 const sp<FakeWindowHandle>& w =
4955 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05004956 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00004957 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4958
4959 touch();
4960
4961 w->consumeMotionOutside();
4962}
4963
4964TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
4965 const sp<FakeWindowHandle>& w =
4966 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
chaviw3277faf2021-05-19 16:45:23 -05004967 w->addFlags(WindowInfo::Flag::WATCH_OUTSIDE_TOUCH);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00004968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4969
4970 touch();
4971
4972 InputEvent* event = w->consume();
4973 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
4974 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
4975 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getX());
4976 EXPECT_EQ(0.0f, motionEvent.getRawPointerCoords(0)->getY());
4977}
4978
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004979TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004980 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00004981 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4982 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00004983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
4984
4985 touch();
4986
4987 mTouchWindow->consumeAnyMotionDown();
4988}
4989
4990TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
4991 const sp<FakeWindowHandle>& w =
4992 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
4993 MAXIMUM_OBSCURING_OPACITY);
4994 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00004995
4996 touch();
4997
4998 mTouchWindow->consumeAnyMotionDown();
4999}
5000
5001TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005002 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005003 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5004 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005005 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5006
5007 touch();
5008
5009 mTouchWindow->assertNoEvents();
5010}
5011
5012TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
5013 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
5014 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005015 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5016 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005017 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005018 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5019 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005020 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5021
5022 touch();
5023
5024 mTouchWindow->assertNoEvents();
5025}
5026
5027TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
5028 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
5029 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005030 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5031 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005032 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005033 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5034 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005035 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5036
5037 touch();
5038
5039 mTouchWindow->consumeAnyMotionDown();
5040}
5041
5042TEST_F(InputDispatcherUntrustedTouchesTest,
5043 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
5044 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005045 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5046 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005047 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005048 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5049 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005050 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5051
5052 touch();
5053
5054 mTouchWindow->consumeAnyMotionDown();
5055}
5056
5057TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
5058 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005059 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5060 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005061 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005062 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5063 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005064 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005065
5066 touch();
5067
5068 mTouchWindow->assertNoEvents();
5069}
5070
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005071TEST_F(InputDispatcherUntrustedTouchesTest,
5072 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
5073 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005074 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5075 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005076 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005077 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5078 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005079 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5080
5081 touch();
5082
5083 mTouchWindow->assertNoEvents();
5084}
5085
5086TEST_F(InputDispatcherUntrustedTouchesTest,
5087 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
5088 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005089 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5090 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005091 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005092 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5093 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005094 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5095
5096 touch();
5097
5098 mTouchWindow->consumeAnyMotionDown();
5099}
5100
5101TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
5102 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005103 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5104 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005105 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5106
5107 touch();
5108
5109 mTouchWindow->consumeAnyMotionDown();
5110}
5111
5112TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
5113 const sp<FakeWindowHandle>& w =
5114 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
5115 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5116
5117 touch();
5118
5119 mTouchWindow->consumeAnyMotionDown();
5120}
5121
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005122TEST_F(InputDispatcherUntrustedTouchesTest,
5123 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
5124 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5125 const sp<FakeWindowHandle>& w =
5126 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
5127 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5128
5129 touch();
5130
5131 mTouchWindow->assertNoEvents();
5132}
5133
5134TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
5135 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5136 const sp<FakeWindowHandle>& w =
5137 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
5138 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5139
5140 touch();
5141
5142 mTouchWindow->consumeAnyMotionDown();
5143}
5144
5145TEST_F(InputDispatcherUntrustedTouchesTest,
5146 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
5147 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
5148 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005149 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5150 OPACITY_ABOVE_THRESHOLD);
5151 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5152
5153 touch();
5154
5155 mTouchWindow->consumeAnyMotionDown();
5156}
5157
5158TEST_F(InputDispatcherUntrustedTouchesTest,
5159 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
5160 const sp<FakeWindowHandle>& w1 =
5161 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5162 OPACITY_BELOW_THRESHOLD);
5163 const sp<FakeWindowHandle>& w2 =
5164 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5165 OPACITY_BELOW_THRESHOLD);
5166 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5167
5168 touch();
5169
5170 mTouchWindow->assertNoEvents();
5171}
5172
5173/**
5174 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
5175 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
5176 * (which alone would result in allowing touches) does not affect the blocking behavior.
5177 */
5178TEST_F(InputDispatcherUntrustedTouchesTest,
5179 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
5180 const sp<FakeWindowHandle>& wB =
5181 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5182 OPACITY_BELOW_THRESHOLD);
5183 const sp<FakeWindowHandle>& wC =
5184 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5185 OPACITY_BELOW_THRESHOLD);
5186 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5187
5188 touch();
5189
5190 mTouchWindow->assertNoEvents();
5191}
5192
5193/**
5194 * This test is testing that a window from a different UID but with same application token doesn't
5195 * block the touch. Apps can share the application token for close UI collaboration for example.
5196 */
5197TEST_F(InputDispatcherUntrustedTouchesTest,
5198 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
5199 const sp<FakeWindowHandle>& w =
5200 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5201 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005202 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5203
5204 touch();
5205
5206 mTouchWindow->consumeAnyMotionDown();
5207}
5208
arthurhungb89ccb02020-12-30 16:19:01 +08005209class InputDispatcherDragTests : public InputDispatcherTest {
5210protected:
5211 std::shared_ptr<FakeApplicationHandle> mApp;
5212 sp<FakeWindowHandle> mWindow;
5213 sp<FakeWindowHandle> mSecondWindow;
5214 sp<FakeWindowHandle> mDragWindow;
5215
5216 void SetUp() override {
5217 InputDispatcherTest::SetUp();
5218 mApp = std::make_shared<FakeApplicationHandle>();
5219 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5220 mWindow->setFrame(Rect(0, 0, 100, 100));
chaviw3277faf2021-05-19 16:45:23 -05005221 mWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005222
5223 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5224 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
chaviw3277faf2021-05-19 16:45:23 -05005225 mSecondWindow->setFlags(WindowInfo::Flag::NOT_TOUCH_MODAL);
arthurhungb89ccb02020-12-30 16:19:01 +08005226
5227 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5228 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5229 }
5230
5231 // Start performing drag, we will create a drag window and transfer touch to it.
5232 void performDrag() {
5233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5234 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5235 {50, 50}))
5236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5237
5238 // Window should receive motion event.
5239 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5240
5241 // The drag window covers the entire display
5242 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5243 mDispatcher->setInputWindows(
5244 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5245
5246 // Transfer touch focus to the drag window
5247 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5248 true /* isDragDrop */);
5249 mWindow->consumeMotionCancel();
5250 mDragWindow->consumeMotionDown();
5251 }
arthurhung6d4bed92021-03-17 11:59:33 +08005252
5253 // Start performing drag, we will create a drag window and transfer touch to it.
5254 void performStylusDrag() {
5255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5256 injectMotionEvent(mDispatcher,
5257 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
5258 AINPUT_SOURCE_STYLUS)
5259 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5260 .pointer(PointerBuilder(0,
5261 AMOTION_EVENT_TOOL_TYPE_STYLUS)
5262 .x(50)
5263 .y(50))
5264 .build()));
5265 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5266
5267 // The drag window covers the entire display
5268 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5269 mDispatcher->setInputWindows(
5270 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5271
5272 // Transfer touch focus to the drag window
5273 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5274 true /* isDragDrop */);
5275 mWindow->consumeMotionCancel();
5276 mDragWindow->consumeMotionDown();
5277 }
arthurhungb89ccb02020-12-30 16:19:01 +08005278};
5279
5280TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
5281 performDrag();
5282
5283 // Move on window.
5284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5285 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5286 ADISPLAY_ID_DEFAULT, {50, 50}))
5287 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5288 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5289 mWindow->consumeDragEvent(false, 50, 50);
5290 mSecondWindow->assertNoEvents();
5291
5292 // Move to another window.
5293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5294 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5295 ADISPLAY_ID_DEFAULT, {150, 50}))
5296 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5297 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5298 mWindow->consumeDragEvent(true, 150, 50);
5299 mSecondWindow->consumeDragEvent(false, 50, 50);
5300
5301 // Move back to original window.
5302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5303 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5304 ADISPLAY_ID_DEFAULT, {50, 50}))
5305 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5306 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5307 mWindow->consumeDragEvent(false, 50, 50);
5308 mSecondWindow->consumeDragEvent(true, -50, 50);
5309
5310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5311 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
5312 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5313 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5314 mWindow->assertNoEvents();
5315 mSecondWindow->assertNoEvents();
5316}
5317
arthurhungf452d0b2021-01-06 00:19:52 +08005318TEST_F(InputDispatcherDragTests, DragAndDrop) {
5319 performDrag();
5320
5321 // Move on window.
5322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5323 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5324 ADISPLAY_ID_DEFAULT, {50, 50}))
5325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5326 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5327 mWindow->consumeDragEvent(false, 50, 50);
5328 mSecondWindow->assertNoEvents();
5329
5330 // Move to another window.
5331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5332 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5333 ADISPLAY_ID_DEFAULT, {150, 50}))
5334 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5335 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5336 mWindow->consumeDragEvent(true, 150, 50);
5337 mSecondWindow->consumeDragEvent(false, 50, 50);
5338
5339 // drop to another window.
5340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5341 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5342 {150, 50}))
5343 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5344 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5345 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5346 mWindow->assertNoEvents();
5347 mSecondWindow->assertNoEvents();
5348}
5349
arthurhung6d4bed92021-03-17 11:59:33 +08005350TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
5351 performStylusDrag();
5352
5353 // Move on window and keep button pressed.
5354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5355 injectMotionEvent(mDispatcher,
5356 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5357 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5358 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5359 .x(50)
5360 .y(50))
5361 .build()))
5362 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5363 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5364 mWindow->consumeDragEvent(false, 50, 50);
5365 mSecondWindow->assertNoEvents();
5366
5367 // Move to another window and release button, expect to drop item.
5368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5369 injectMotionEvent(mDispatcher,
5370 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5371 .buttonState(0)
5372 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5373 .x(150)
5374 .y(50))
5375 .build()))
5376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5377 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5378 mWindow->assertNoEvents();
5379 mSecondWindow->assertNoEvents();
5380 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5381
5382 // nothing to the window.
5383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5384 injectMotionEvent(mDispatcher,
5385 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
5386 .buttonState(0)
5387 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5388 .x(150)
5389 .y(50))
5390 .build()))
5391 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5392 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5393 mWindow->assertNoEvents();
5394 mSecondWindow->assertNoEvents();
5395}
5396
Arthur Hung6d0571e2021-04-09 20:18:16 +08005397TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
5398 performDrag();
5399
5400 // Set second window invisible.
5401 mSecondWindow->setVisible(false);
5402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5403
5404 // Move on window.
5405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5406 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5407 ADISPLAY_ID_DEFAULT, {50, 50}))
5408 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5409 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5410 mWindow->consumeDragEvent(false, 50, 50);
5411 mSecondWindow->assertNoEvents();
5412
5413 // Move to another window.
5414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5415 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5416 ADISPLAY_ID_DEFAULT, {150, 50}))
5417 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5418 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5419 mWindow->consumeDragEvent(true, 150, 50);
5420 mSecondWindow->assertNoEvents();
5421
5422 // drop to another window.
5423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5424 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5425 {150, 50}))
5426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5427 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5428 mFakePolicy->assertDropTargetEquals(nullptr);
5429 mWindow->assertNoEvents();
5430 mSecondWindow->assertNoEvents();
5431}
5432
Garfield Tane84e6f92019-08-29 17:28:41 -07005433} // namespace android::inputdispatcher