blob: ae8358aa5dddf4202390c7f1b5fb6295a0087061 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070019#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080020#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080021#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070022#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070023#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000024#include <fcntl.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080025#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100026#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080027#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080028#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100029
Garfield Tan1c7bc862020-01-28 13:24:04 -080030#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070031#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080032#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080033#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080034
Garfield Tan1c7bc862020-01-28 13:24:04 -080035using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050036using android::gui::FocusRequest;
37using android::gui::TouchOcclusionMode;
38using android::gui::WindowInfo;
39using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080040using android::os::InputEventInjectionResult;
41using android::os::InputEventInjectionSync;
Michael Wright44753b12020-07-08 13:48:11 +010042using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080043
Garfield Tane84e6f92019-08-29 17:28:41 -070044namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080045
46// An arbitrary time value.
47static const nsecs_t ARBITRARY_TIME = 1234;
48
49// An arbitrary device id.
50static const int32_t DEVICE_ID = 1;
51
Jeff Brownf086ddb2014-02-11 14:28:48 -080052// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000053static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
54static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080055
Michael Wrightd02c5b62014-02-10 15:10:22 -080056// An arbitrary injector pid / uid pair that has permission to inject events.
57static const int32_t INJECTOR_PID = 999;
58static const int32_t INJECTOR_UID = 1001;
59
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000060// An arbitrary pid of the gesture monitor window
61static constexpr int32_t MONITOR_PID = 2001;
62
chaviwd1c23182019-12-20 18:44:56 -080063struct PointF {
64 float x;
65 float y;
66};
Michael Wrightd02c5b62014-02-10 15:10:22 -080067
Gang Wang342c9272020-01-13 13:15:04 -050068/**
69 * Return a DOWN key event with KEYCODE_A.
70 */
71static KeyEvent getTestKeyEvent() {
72 KeyEvent event;
73
Garfield Tanfbe732e2020-01-24 11:26:14 -080074 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
75 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
76 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050077 return event;
78}
79
Siarhei Vishniakouca205502021-07-16 21:31:58 +000080static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
81 ASSERT_EQ(expectedAction, receivedAction)
82 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
83 << MotionEvent::actionToString(receivedAction);
84}
85
Michael Wrightd02c5b62014-02-10 15:10:22 -080086// --- FakeInputDispatcherPolicy ---
87
88class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
89 InputDispatcherConfiguration mConfig;
90
91protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100092 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080093
94public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100095 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080096
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080097 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -070098 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
99 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
100 EXPECT_EQ(event.getDisplayId(), args.displayId);
101
102 const auto& keyEvent = static_cast<const KeyEvent&>(event);
103 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
104 EXPECT_EQ(keyEvent.getAction(), args.action);
105 });
Jackal Guof9696682018-10-05 12:23:23 +0800106 }
107
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700108 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
109 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
110 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
111 EXPECT_EQ(event.getDisplayId(), args.displayId);
112
113 const auto& motionEvent = static_cast<const MotionEvent&>(event);
114 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
115 EXPECT_EQ(motionEvent.getAction(), args.action);
116 EXPECT_EQ(motionEvent.getX(0), point.x);
117 EXPECT_EQ(motionEvent.getY(0), point.y);
118 EXPECT_EQ(motionEvent.getRawX(0), point.x);
119 EXPECT_EQ(motionEvent.getRawY(0), point.y);
120 });
Jackal Guof9696682018-10-05 12:23:23 +0800121 }
122
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700123 void assertFilterInputEventWasNotCalled() {
124 std::scoped_lock lock(mLock);
125 ASSERT_EQ(nullptr, mFilteredEvent);
126 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800127
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800128 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700129 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800130 ASSERT_TRUE(mConfigurationChangedTime)
131 << "Timed out waiting for configuration changed call";
132 ASSERT_EQ(*mConfigurationChangedTime, when);
133 mConfigurationChangedTime = std::nullopt;
134 }
135
136 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700137 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800138 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800139 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800140 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
141 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
142 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
143 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
144 mLastNotifySwitch = std::nullopt;
145 }
146
chaviwfd6d3512019-03-25 13:23:49 -0700147 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700148 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800149 ASSERT_EQ(touchedToken, mOnPointerDownToken);
150 mOnPointerDownToken.clear();
151 }
152
153 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700154 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800155 ASSERT_TRUE(mOnPointerDownToken == nullptr)
156 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700157 }
158
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700159 // This function must be called soon after the expected ANR timer starts,
160 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500161 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700162 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500163 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
164 std::shared_ptr<InputApplicationHandle> application;
165 { // acquire lock
166 std::unique_lock lock(mLock);
167 android::base::ScopedLockAssertion assumeLocked(mLock);
168 ASSERT_NO_FATAL_FAILURE(
169 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
170 } // release lock
171 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700172 }
173
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000174 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
175 const sp<IBinder>& expectedConnectionToken) {
176 sp<IBinder> connectionToken = getUnresponsiveWindowToken(timeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500177 ASSERT_EQ(expectedConnectionToken, connectionToken);
178 }
179
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000180 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
181 sp<IBinder> connectionToken = getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500182 ASSERT_EQ(expectedConnectionToken, connectionToken);
183 }
184
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000185 void assertNotifyMonitorUnresponsiveWasCalled(std::chrono::nanoseconds timeout) {
186 int32_t pid = getUnresponsiveMonitorPid(timeout);
187 ASSERT_EQ(MONITOR_PID, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500188 }
189
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000190 void assertNotifyMonitorResponsiveWasCalled() {
191 int32_t pid = getResponsiveMonitorPid();
192 ASSERT_EQ(MONITOR_PID, pid);
193 }
194
195 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500196 std::unique_lock lock(mLock);
197 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000198 return getAnrTokenLockedInterruptible(timeout, mAnrWindowTokens, lock);
199 }
200
201 sp<IBinder> getResponsiveWindowToken() {
202 std::unique_lock lock(mLock);
203 android::base::ScopedLockAssertion assumeLocked(mLock);
204 return getAnrTokenLockedInterruptible(0s, mResponsiveWindowTokens, lock);
205 }
206
207 int32_t getUnresponsiveMonitorPid(std::chrono::nanoseconds timeout) {
208 std::unique_lock lock(mLock);
209 android::base::ScopedLockAssertion assumeLocked(mLock);
210 return getAnrTokenLockedInterruptible(timeout, mAnrMonitorPids, lock);
211 }
212
213 int32_t getResponsiveMonitorPid() {
214 std::unique_lock lock(mLock);
215 android::base::ScopedLockAssertion assumeLocked(mLock);
216 return getAnrTokenLockedInterruptible(0s, mResponsiveMonitorPids, lock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500217 }
218
219 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
220 // for a specific container to become non-empty. When the container is non-empty, return the
221 // first entry from the container and erase it.
222 template <class T>
223 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
224 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700225 // If there is an ANR, Dispatcher won't be idle because there are still events
226 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
227 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
229 // to provide it some time to act. 100ms seems reasonable.
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800230 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
231 const std::chrono::time_point start = std::chrono::steady_clock::now();
232 std::optional<T> token =
233 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
234 if (!token.has_value()) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500235 ADD_FAILURE() << "Did not receive the ANR callback";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000236 return {};
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700237 }
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800238
239 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700240 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
241 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700242 if (std::chrono::abs(timeout - waited) > 100ms) {
243 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
244 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
245 << "ms, but waited "
246 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
247 << "ms instead";
248 }
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800249 return *token;
250 }
251
252 template <class T>
253 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
254 std::queue<T>& storage,
255 std::unique_lock<std::mutex>& lock,
256 std::condition_variable& condition)
257 REQUIRES(mLock) {
258 condition.wait_for(lock, timeout,
259 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
260 if (storage.empty()) {
261 ADD_FAILURE() << "Did not receive the expected callback";
262 return std::nullopt;
263 }
264 T item = storage.front();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500265 storage.pop();
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800266 return std::make_optional(item);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700267 }
268
269 void assertNotifyAnrWasNotCalled() {
270 std::scoped_lock lock(mLock);
271 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000272 ASSERT_TRUE(mAnrWindowTokens.empty());
273 ASSERT_TRUE(mAnrMonitorPids.empty());
274 ASSERT_TRUE(mResponsiveWindowTokens.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500275 << "ANR was not called, but please also consume the 'connection is responsive' "
276 "signal";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000277 ASSERT_TRUE(mResponsiveMonitorPids.empty())
278 << "Monitor ANR was not called, but please also consume the 'monitor is responsive'"
279 " signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700280 }
281
Garfield Tan1c7bc862020-01-28 13:24:04 -0800282 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
283 mConfig.keyRepeatTimeout = timeout;
284 mConfig.keyRepeatDelay = delay;
285 }
286
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000287 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800288 std::unique_lock lock(mLock);
289 base::ScopedLockAssertion assumeLocked(mLock);
290
291 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
292 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000293 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800294 enabled;
295 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000296 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
297 << ") to be called.";
298 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800299 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000300 auto request = *mPointerCaptureRequest;
301 mPointerCaptureRequest.reset();
302 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800303 }
304
305 void assertSetPointerCaptureNotCalled() {
306 std::unique_lock lock(mLock);
307 base::ScopedLockAssertion assumeLocked(mLock);
308
309 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000310 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800311 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000312 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800313 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000314 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800315 }
316
arthurhungf452d0b2021-01-06 00:19:52 +0800317 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
318 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800319 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800320 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800321 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800322 }
323
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800324 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
325 std::unique_lock lock(mLock);
326 base::ScopedLockAssertion assumeLocked(mLock);
327 std::optional<sp<IBinder>> receivedToken =
328 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
329 mNotifyInputChannelBroken);
330 ASSERT_TRUE(receivedToken.has_value());
331 ASSERT_EQ(token, *receivedToken);
332 }
333
Michael Wrightd02c5b62014-02-10 15:10:22 -0800334private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700335 std::mutex mLock;
336 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
337 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
338 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
339 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800340
Prabir Pradhan99987712020-11-10 18:43:05 -0800341 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000342
343 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800344
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700345 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700346 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000347 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
348 std::queue<sp<IBinder>> mResponsiveWindowTokens GUARDED_BY(mLock);
349 std::queue<int32_t> mAnrMonitorPids GUARDED_BY(mLock);
350 std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700351 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800352 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
353 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700354
arthurhungf452d0b2021-01-06 00:19:52 +0800355 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800356 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800357
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600358 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700359 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800360 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800361 }
362
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000363 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700364 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000365 mAnrWindowTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700366 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500367 }
368
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000369 void notifyMonitorUnresponsive(int32_t pid, const std::string&) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500370 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000371 mAnrMonitorPids.push(pid);
372 mNotifyAnr.notify_all();
373 }
374
375 void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {
376 std::scoped_lock lock(mLock);
377 mResponsiveWindowTokens.push(connectionToken);
378 mNotifyAnr.notify_all();
379 }
380
381 void notifyMonitorResponsive(int32_t pid) override {
382 std::scoped_lock lock(mLock);
383 mResponsiveMonitorPids.push(pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500384 mNotifyAnr.notify_all();
385 }
386
387 void notifyNoFocusedWindowAnr(
388 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
389 std::scoped_lock lock(mLock);
390 mAnrApplications.push(applicationHandle);
391 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800392 }
393
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800394 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
395 std::scoped_lock lock(mLock);
396 mBrokenInputChannels.push(connectionToken);
397 mNotifyInputChannelBroken.notify_all();
398 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800399
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600400 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700401
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600402 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Chris Yef59a2f42020-10-16 12:55:26 -0700403 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
404 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
405 const std::vector<float>& values) override {}
406
407 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
408 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000409
Chris Yefb552902021-02-03 17:18:37 -0800410 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
411
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600412 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800413 *outConfig = mConfig;
414 }
415
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600416 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700417 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800418 switch (inputEvent->getType()) {
419 case AINPUT_EVENT_TYPE_KEY: {
420 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800421 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800422 break;
423 }
424
425 case AINPUT_EVENT_TYPE_MOTION: {
426 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800427 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800428 break;
429 }
430 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800431 return true;
432 }
433
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600434 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800435
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600436 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800437
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600438 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800439 return 0;
440 }
441
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600442 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800443 return false;
444 }
445
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600446 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
447 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700448 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800449 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
450 * essentially a passthrough for notifySwitch.
451 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800452 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800453 }
454
Sean Stoutb4e0a592021-02-23 07:34:53 -0800455 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800456
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800457 bool checkInjectEventsPermissionNonReentrant(int32_t pid, int32_t uid) override {
458 return pid == INJECTOR_PID && uid == INJECTOR_UID;
459 }
Jackal Guof9696682018-10-05 12:23:23 +0800460
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600461 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700462 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700463 mOnPointerDownToken = newToken;
464 }
465
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000466 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800467 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000468 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800469 mPointerCaptureChangedCondition.notify_all();
470 }
471
arthurhungf452d0b2021-01-06 00:19:52 +0800472 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
473 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800474 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800475 mDropTargetWindowToken = token;
476 }
477
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700478 void assertFilterInputEventWasCalledInternal(
479 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700480 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800481 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700482 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800483 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800484 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800485};
486
Michael Wrightd02c5b62014-02-10 15:10:22 -0800487// --- InputDispatcherTest ---
488
489class InputDispatcherTest : public testing::Test {
490protected:
491 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700492 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800493
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000494 void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800495 mFakePolicy = new FakeInputDispatcherPolicy();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700496 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800497 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000498 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700499 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800500 }
501
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000502 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700503 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700505 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800506 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700507
508 /**
509 * Used for debugging when writing the test
510 */
511 void dumpDispatcherState() {
512 std::string dump;
513 mDispatcher->dump(dump);
514 std::stringstream ss(dump);
515 std::string to;
516
517 while (std::getline(ss, to, '\n')) {
518 ALOGE("%s", to.c_str());
519 }
520 }
Vishnu Nair958da932020-08-21 17:12:37 -0700521
chaviw3277faf2021-05-19 16:45:23 -0500522 void setFocusedWindow(const sp<WindowInfoHandle>& window,
523 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700524 FocusRequest request;
525 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000526 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700527 if (focusedWindow) {
528 request.focusedToken = focusedWindow->getToken();
529 }
530 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
531 request.displayId = window->getInfo()->displayId;
532 mDispatcher->setFocusedWindow(request);
533 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800534};
535
Michael Wrightd02c5b62014-02-10 15:10:22 -0800536TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
537 KeyEvent event;
538
539 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800540 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
541 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600542 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
543 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800544 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700545 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800546 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800547 << "Should reject key events with undefined action.";
548
549 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800550 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
551 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600552 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800553 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700554 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800555 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800556 << "Should reject key events with ACTION_MULTIPLE.";
557}
558
559TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
560 MotionEvent event;
561 PointerProperties pointerProperties[MAX_POINTERS + 1];
562 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800563 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800564 pointerProperties[i].clear();
565 pointerProperties[i].id = i;
566 pointerCoords[i].clear();
567 }
568
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800569 // Some constants commonly used below
570 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
571 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
572 constexpr int32_t metaState = AMETA_NONE;
573 constexpr MotionClassification classification = MotionClassification::NONE;
574
chaviw9eaa22c2020-07-01 16:21:27 -0700575 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800577 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700578 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
579 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700580 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
581 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700582 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800583 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700584 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800585 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586 << "Should reject motion events with undefined action.";
587
588 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800589 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700590 AMOTION_EVENT_ACTION_POINTER_DOWN |
591 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700592 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
593 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700594 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500595 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800596 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700597 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800598 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 << "Should reject motion events with pointer down index too large.";
600
Garfield Tanfbe732e2020-01-24 11:26:14 -0800601 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700602 AMOTION_EVENT_ACTION_POINTER_DOWN |
603 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700604 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
605 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700606 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500607 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800608 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700609 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800610 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800611 << "Should reject motion events with pointer down index too small.";
612
613 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800614 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700615 AMOTION_EVENT_ACTION_POINTER_UP |
616 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700617 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
618 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700619 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500620 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800621 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700622 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800623 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800624 << "Should reject motion events with pointer up index too large.";
625
Garfield Tanfbe732e2020-01-24 11:26:14 -0800626 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700627 AMOTION_EVENT_ACTION_POINTER_UP |
628 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700629 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
630 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700631 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500632 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800633 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700634 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800635 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800636 << "Should reject motion events with pointer up index too small.";
637
638 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800639 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
640 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700641 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700642 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
643 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700644 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800645 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700646 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800647 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800648 << "Should reject motion events with 0 pointers.";
649
Garfield Tanfbe732e2020-01-24 11:26:14 -0800650 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
651 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700652 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700653 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
654 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700655 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800656 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700657 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800658 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659 << "Should reject motion events with more than MAX_POINTERS pointers.";
660
661 // Rejects motion events with invalid pointer ids.
662 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800663 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
664 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700665 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700666 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
667 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700668 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800669 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700670 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800671 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800672 << "Should reject motion events with pointer ids less than 0.";
673
674 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800675 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
676 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700677 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700678 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
679 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700680 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800681 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700682 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800684 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
685
686 // Rejects motion events with duplicate pointer ids.
687 pointerProperties[0].id = 1;
688 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800689 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
690 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700691 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700692 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
693 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700694 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800695 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700696 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800697 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800698 << "Should reject motion events with duplicate pointer ids.";
699}
700
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800701/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
702
703TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
704 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800705 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800706 mDispatcher->notifyConfigurationChanged(&args);
707 ASSERT_TRUE(mDispatcher->waitForIdle());
708
709 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
710}
711
712TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800713 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
714 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800715 mDispatcher->notifySwitch(&args);
716
717 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
718 args.policyFlags |= POLICY_FLAG_TRUSTED;
719 mFakePolicy->assertNotifySwitchWasCalled(args);
720}
721
Arthur Hungb92218b2018-08-14 12:00:21 +0800722// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700723static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700724// Default input dispatching timeout if there is no focused application or paused window
725// from which to determine an appropriate dispatching timeout.
726static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
727 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
728 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800729
730class FakeApplicationHandle : public InputApplicationHandle {
731public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700732 FakeApplicationHandle() {
733 mInfo.name = "Fake Application";
734 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500735 mInfo.dispatchingTimeoutMillis =
736 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700737 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800738 virtual ~FakeApplicationHandle() {}
739
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000740 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700741
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500742 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
743 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700744 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800745};
746
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800747class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800748public:
Garfield Tan15601662020-09-22 15:32:38 -0700749 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800750 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700751 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800752 }
753
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800754 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700755 InputEvent* event;
756 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
757 if (!consumeSeq) {
758 return nullptr;
759 }
760 finishEvent(*consumeSeq);
761 return event;
762 }
763
764 /**
765 * Receive an event without acknowledging it.
766 * Return the sequence number that could later be used to send finished signal.
767 */
768 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800769 uint32_t consumeSeq;
770 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800771
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800772 std::chrono::time_point start = std::chrono::steady_clock::now();
773 status_t status = WOULD_BLOCK;
774 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800775 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800776 &event);
777 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
778 if (elapsed > 100ms) {
779 break;
780 }
781 }
782
783 if (status == WOULD_BLOCK) {
784 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700785 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800786 }
787
788 if (status != OK) {
789 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700790 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800791 }
792 if (event == nullptr) {
793 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700794 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800795 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700796 if (outEvent != nullptr) {
797 *outEvent = event;
798 }
799 return consumeSeq;
800 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800801
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700802 /**
803 * To be used together with "receiveEvent" to complete the consumption of an event.
804 */
805 void finishEvent(uint32_t consumeSeq) {
806 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
807 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800808 }
809
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000810 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
811 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
812 ASSERT_EQ(OK, status);
813 }
814
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000815 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
816 std::optional<int32_t> expectedDisplayId,
817 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800818 InputEvent* event = consume();
819
820 ASSERT_NE(nullptr, event) << mName.c_str()
821 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800822 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700823 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800824 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800825
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000826 if (expectedDisplayId.has_value()) {
827 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
828 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800829
Tiger Huang8664f8c2018-10-11 19:14:35 +0800830 switch (expectedEventType) {
831 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800832 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
833 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000834 if (expectedFlags.has_value()) {
835 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
836 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800837 break;
838 }
839 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800840 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000841 assertMotionAction(expectedAction, motionEvent.getAction());
842
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000843 if (expectedFlags.has_value()) {
844 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
845 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800846 break;
847 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100848 case AINPUT_EVENT_TYPE_FOCUS: {
849 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
850 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800851 case AINPUT_EVENT_TYPE_CAPTURE: {
852 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
853 }
Antonio Kantekf16f2832021-09-28 04:39:20 +0000854 case AINPUT_EVENT_TYPE_TOUCH_MODE: {
855 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
856 }
arthurhungb89ccb02020-12-30 16:19:01 +0800857 case AINPUT_EVENT_TYPE_DRAG: {
858 FAIL() << "Use 'consumeDragEvent' for DRAG events";
859 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800860 default: {
861 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
862 }
863 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800864 }
865
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100866 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
867 InputEvent* event = consume();
868 ASSERT_NE(nullptr, event) << mName.c_str()
869 << ": consumer should have returned non-NULL event.";
870 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
871 << "Got " << inputEventTypeToString(event->getType())
872 << " event instead of FOCUS event";
873
874 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
875 << mName.c_str() << ": event displayId should always be NONE.";
876
877 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
878 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100879 }
880
Prabir Pradhan99987712020-11-10 18:43:05 -0800881 void consumeCaptureEvent(bool hasCapture) {
882 const InputEvent* event = consume();
883 ASSERT_NE(nullptr, event) << mName.c_str()
884 << ": consumer should have returned non-NULL event.";
885 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
886 << "Got " << inputEventTypeToString(event->getType())
887 << " event instead of CAPTURE event";
888
889 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
890 << mName.c_str() << ": event displayId should always be NONE.";
891
892 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
893 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
894 }
895
arthurhungb89ccb02020-12-30 16:19:01 +0800896 void consumeDragEvent(bool isExiting, float x, float y) {
897 const InputEvent* event = consume();
898 ASSERT_NE(nullptr, event) << mName.c_str()
899 << ": consumer should have returned non-NULL event.";
900 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
901 << "Got " << inputEventTypeToString(event->getType())
902 << " event instead of DRAG event";
903
904 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
905 << mName.c_str() << ": event displayId should always be NONE.";
906
907 const auto& dragEvent = static_cast<const DragEvent&>(*event);
908 EXPECT_EQ(isExiting, dragEvent.isExiting());
909 EXPECT_EQ(x, dragEvent.getX());
910 EXPECT_EQ(y, dragEvent.getY());
911 }
912
Antonio Kantekf16f2832021-09-28 04:39:20 +0000913 void consumeTouchModeEvent(bool inTouchMode) {
914 const InputEvent* event = consume();
915 ASSERT_NE(nullptr, event) << mName.c_str()
916 << ": consumer should have returned non-NULL event.";
917 ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
918 << "Got " << inputEventTypeToString(event->getType())
919 << " event instead of TOUCH_MODE event";
920
921 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
922 << mName.c_str() << ": event displayId should always be NONE.";
923 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
924 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
925 }
926
chaviwd1c23182019-12-20 18:44:56 -0800927 void assertNoEvents() {
928 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700929 if (event == nullptr) {
930 return;
931 }
932 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
933 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
934 ADD_FAILURE() << "Received key event "
935 << KeyEvent::actionToString(keyEvent.getAction());
936 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
937 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
938 ADD_FAILURE() << "Received motion event "
939 << MotionEvent::actionToString(motionEvent.getAction());
940 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
941 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
942 ADD_FAILURE() << "Received focus event, hasFocus = "
943 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800944 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
945 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
946 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
947 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Antonio Kantekf16f2832021-09-28 04:39:20 +0000948 } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
949 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
950 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
951 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700952 }
953 FAIL() << mName.c_str()
954 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800955 }
956
957 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
958
Prabir Pradhan07e05b62021-11-19 03:57:24 -0800959 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
960
chaviwd1c23182019-12-20 18:44:56 -0800961protected:
962 std::unique_ptr<InputConsumer> mConsumer;
963 PreallocatedInputEventFactory mEventFactory;
964
965 std::string mName;
966};
967
chaviw3277faf2021-05-19 16:45:23 -0500968class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -0800969public:
970 static const int32_t WIDTH = 600;
971 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800972
Chris Yea209fde2020-07-22 13:54:51 -0700973 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700974 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500975 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800976 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500977 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700978 base::Result<std::unique_ptr<InputChannel>> channel =
979 dispatcher->createInputChannel(name);
980 token = (*channel)->getConnectionToken();
981 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800982 }
983
984 inputApplicationHandle->updateInfo();
985 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
986
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500987 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700988 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800989 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500990 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000991 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -0800992 mInfo.frameLeft = 0;
993 mInfo.frameTop = 0;
994 mInfo.frameRight = WIDTH;
995 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700996 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800997 mInfo.globalScaleFactor = 1.0;
998 mInfo.touchableRegion.clear();
999 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
chaviwd1c23182019-12-20 18:44:56 -08001000 mInfo.ownerPid = INJECTOR_PID;
1001 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -08001002 mInfo.displayId = displayId;
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001003 mInfo.inputConfig = WindowInfo::InputConfig::NONE;
chaviwd1c23182019-12-20 18:44:56 -08001004 }
1005
Arthur Hungabbb9d82021-09-01 14:52:30 +00001006 sp<FakeWindowHandle> clone(
1007 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001008 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001009 sp<FakeWindowHandle> handle =
1010 new FakeWindowHandle(inputApplicationHandle, dispatcher, mInfo.name + "(Mirror)",
1011 displayId, mInfo.token);
1012 return handle;
1013 }
1014
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001015 void setTouchable(bool touchable) {
1016 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1017 }
chaviwd1c23182019-12-20 18:44:56 -08001018
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001019 void setFocusable(bool focusable) {
1020 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1021 }
1022
1023 void setVisible(bool visible) {
1024 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1025 }
Vishnu Nair958da932020-08-21 17:12:37 -07001026
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001027 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001028 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001029 }
1030
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001031 void setPaused(bool paused) {
1032 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1033 }
1034
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001035 void setPreventSplitting(bool preventSplitting) {
1036 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001037 }
1038
1039 void setSlippery(bool slippery) {
1040 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1041 }
1042
1043 void setWatchOutsideTouch(bool watchOutside) {
1044 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1045 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001046
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001047 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1048
chaviw3277faf2021-05-19 16:45:23 -05001049 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001050
Bernardo Rufino7393d172021-02-26 13:56:11 +00001051 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1052
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001053 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001054 mInfo.frameLeft = frame.left;
1055 mInfo.frameTop = frame.top;
1056 mInfo.frameRight = frame.right;
1057 mInfo.frameBottom = frame.bottom;
1058 mInfo.touchableRegion.clear();
1059 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001060
1061 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1062 ui::Transform translate;
1063 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1064 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001065 }
1066
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001067 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1068
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001069 void setIsWallpaper(bool isWallpaper) {
1070 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1071 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001072
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001073 void setDupTouchToWallpaper(bool hasWallpaper) {
1074 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1075 }
chaviwd1c23182019-12-20 18:44:56 -08001076
Prabir Pradhand65552b2021-10-07 11:23:50 -07001077 void setInputFeatures(Flags<WindowInfo::Feature> features) { mInfo.inputFeatures = features; }
1078
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001079 void setTrustedOverlay(bool trustedOverlay) {
1080 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1081 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001082
chaviw9eaa22c2020-07-01 16:21:27 -07001083 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1084 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1085 }
1086
1087 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001088
yunho.shinf4a80b82020-11-16 21:13:57 +09001089 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1090
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001091 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1092 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1093 expectedFlags);
1094 }
1095
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001096 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1097 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1098 }
1099
Svet Ganov5d3bc372020-01-26 23:11:07 -08001100 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001101 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001102 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
1103 expectedFlags);
1104 }
1105
1106 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001107 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001108 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
1109 expectedFlags);
1110 }
1111
1112 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001113 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001114 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1115 }
1116
1117 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1118 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001119 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1120 expectedFlags);
1121 }
1122
Svet Ganov5d3bc372020-01-26 23:11:07 -08001123 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001124 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1125 int32_t expectedFlags = 0) {
1126 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1127 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001128 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1129 }
1130
1131 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001132 int32_t expectedFlags = 0) {
1133 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1134 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001135 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1136 }
1137
1138 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001139 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001140 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1141 expectedFlags);
1142 }
1143
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001144 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1145 int32_t expectedFlags = 0) {
1146 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1147 expectedFlags);
1148 }
1149
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001150 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1151 int32_t expectedFlags = 0) {
1152 InputEvent* event = consume();
1153 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
1154 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1155 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1156 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1157 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1158 }
1159
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001160 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1161 ASSERT_NE(mInputReceiver, nullptr)
1162 << "Cannot consume events from a window with no receiver";
1163 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1164 }
1165
Prabir Pradhan99987712020-11-10 18:43:05 -08001166 void consumeCaptureEvent(bool hasCapture) {
1167 ASSERT_NE(mInputReceiver, nullptr)
1168 << "Cannot consume events from a window with no receiver";
1169 mInputReceiver->consumeCaptureEvent(hasCapture);
1170 }
1171
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001172 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1173 std::optional<int32_t> expectedDisplayId,
1174 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001175 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1176 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1177 expectedFlags);
1178 }
1179
arthurhungb89ccb02020-12-30 16:19:01 +08001180 void consumeDragEvent(bool isExiting, float x, float y) {
1181 mInputReceiver->consumeDragEvent(isExiting, x, y);
1182 }
1183
Antonio Kantekf16f2832021-09-28 04:39:20 +00001184 void consumeTouchModeEvent(bool inTouchMode) {
1185 ASSERT_NE(mInputReceiver, nullptr)
1186 << "Cannot consume events from a window with no receiver";
1187 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1188 }
1189
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001190 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001191 if (mInputReceiver == nullptr) {
1192 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1193 return std::nullopt;
1194 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001195 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001196 }
1197
1198 void finishEvent(uint32_t sequenceNum) {
1199 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1200 mInputReceiver->finishEvent(sequenceNum);
1201 }
1202
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001203 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1204 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1205 mInputReceiver->sendTimeline(inputEventId, timeline);
1206 }
1207
chaviwaf87b3e2019-10-01 16:59:28 -07001208 InputEvent* consume() {
1209 if (mInputReceiver == nullptr) {
1210 return nullptr;
1211 }
1212 return mInputReceiver->consume();
1213 }
1214
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001215 MotionEvent* consumeMotion() {
1216 InputEvent* event = consume();
1217 if (event == nullptr) {
1218 ADD_FAILURE() << "Consume failed : no event";
1219 return nullptr;
1220 }
1221 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1222 ADD_FAILURE() << "Instead of motion event, got "
1223 << inputEventTypeToString(event->getType());
1224 return nullptr;
1225 }
1226 return static_cast<MotionEvent*>(event);
1227 }
1228
Arthur Hungb92218b2018-08-14 12:00:21 +08001229 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001230 if (mInputReceiver == nullptr &&
chaviw3277faf2021-05-19 16:45:23 -05001231 mInfo.inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001232 return; // Can't receive events if the window does not have input channel
1233 }
1234 ASSERT_NE(nullptr, mInputReceiver)
1235 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001236 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001237 }
1238
chaviwaf87b3e2019-10-01 16:59:28 -07001239 sp<IBinder> getToken() { return mInfo.token; }
1240
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001241 const std::string& getName() { return mName; }
1242
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001243 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1244 mInfo.ownerPid = ownerPid;
1245 mInfo.ownerUid = ownerUid;
1246 }
1247
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001248 void destroyReceiver() { mInputReceiver = nullptr; }
1249
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001250 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1251
chaviwd1c23182019-12-20 18:44:56 -08001252private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001253 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001254 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001255 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001256};
1257
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001258std::atomic<int32_t> FakeWindowHandle::sId{1};
1259
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001260static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001261 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001262 int32_t displayId = ADISPLAY_ID_NONE,
1263 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001264 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1265 bool allowKeyRepeat = true) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001266 KeyEvent event;
1267 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1268
1269 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001270 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001271 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1272 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001273
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001274 int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
1275 if (!allowKeyRepeat) {
1276 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1277 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001278 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001279 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001280 injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001281}
1282
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001283static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001284 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001285 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1286}
1287
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001288// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1289// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1290// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001291static InputEventInjectionResult injectKeyDownNoRepeat(
1292 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001293 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1294 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1295 /* allowKeyRepeat */ false);
1296}
1297
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001298static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001299 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001300 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1301}
1302
Garfield Tandf26e862020-07-01 20:18:19 -07001303class PointerBuilder {
1304public:
1305 PointerBuilder(int32_t id, int32_t toolType) {
1306 mProperties.clear();
1307 mProperties.id = id;
1308 mProperties.toolType = toolType;
1309 mCoords.clear();
1310 }
1311
1312 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1313
1314 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1315
1316 PointerBuilder& axis(int32_t axis, float value) {
1317 mCoords.setAxisValue(axis, value);
1318 return *this;
1319 }
1320
1321 PointerProperties buildProperties() const { return mProperties; }
1322
1323 PointerCoords buildCoords() const { return mCoords; }
1324
1325private:
1326 PointerProperties mProperties;
1327 PointerCoords mCoords;
1328};
1329
1330class MotionEventBuilder {
1331public:
1332 MotionEventBuilder(int32_t action, int32_t source) {
1333 mAction = action;
1334 mSource = source;
1335 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1336 }
1337
1338 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1339 mEventTime = eventTime;
1340 return *this;
1341 }
1342
1343 MotionEventBuilder& displayId(int32_t displayId) {
1344 mDisplayId = displayId;
1345 return *this;
1346 }
1347
1348 MotionEventBuilder& actionButton(int32_t actionButton) {
1349 mActionButton = actionButton;
1350 return *this;
1351 }
1352
arthurhung6d4bed92021-03-17 11:59:33 +08001353 MotionEventBuilder& buttonState(int32_t buttonState) {
1354 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001355 return *this;
1356 }
1357
1358 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1359 mRawXCursorPosition = rawXCursorPosition;
1360 return *this;
1361 }
1362
1363 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1364 mRawYCursorPosition = rawYCursorPosition;
1365 return *this;
1366 }
1367
1368 MotionEventBuilder& pointer(PointerBuilder pointer) {
1369 mPointers.push_back(pointer);
1370 return *this;
1371 }
1372
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001373 MotionEventBuilder& addFlag(uint32_t flags) {
1374 mFlags |= flags;
1375 return *this;
1376 }
1377
Garfield Tandf26e862020-07-01 20:18:19 -07001378 MotionEvent build() {
1379 std::vector<PointerProperties> pointerProperties;
1380 std::vector<PointerCoords> pointerCoords;
1381 for (const PointerBuilder& pointer : mPointers) {
1382 pointerProperties.push_back(pointer.buildProperties());
1383 pointerCoords.push_back(pointer.buildCoords());
1384 }
1385
1386 // Set mouse cursor position for the most common cases to avoid boilerplate.
1387 if (mSource == AINPUT_SOURCE_MOUSE &&
1388 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1389 mPointers.size() == 1) {
1390 mRawXCursorPosition = pointerCoords[0].getX();
1391 mRawYCursorPosition = pointerCoords[0].getY();
1392 }
1393
1394 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001395 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001396 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001397 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001398 mButtonState, MotionClassification::NONE, identityTransform,
1399 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001400 mRawYCursorPosition, identityTransform, mEventTime, mEventTime,
1401 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001402
1403 return event;
1404 }
1405
1406private:
1407 int32_t mAction;
1408 int32_t mSource;
1409 nsecs_t mEventTime;
1410 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1411 int32_t mActionButton{0};
1412 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001413 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001414 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1415 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1416
1417 std::vector<PointerBuilder> mPointers;
1418};
1419
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001420static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001421 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001422 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001423 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001424 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1425 injectionTimeout,
1426 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1427}
1428
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001429static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001430 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001431 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001432 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001433 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1434 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001435 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001436 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001437 MotionEvent event = MotionEventBuilder(action, source)
1438 .displayId(displayId)
1439 .eventTime(eventTime)
1440 .rawXCursorPosition(cursorPosition.x)
1441 .rawYCursorPosition(cursorPosition.y)
1442 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1443 .x(position.x)
1444 .y(position.y))
1445 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001446
1447 // Inject event until dispatch out.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001448 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode);
Arthur Hungb92218b2018-08-14 12:00:21 +08001449}
1450
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001451static InputEventInjectionResult injectMotionDown(
1452 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1453 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001454 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001455}
1456
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001457static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001458 int32_t source, int32_t displayId,
1459 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001460 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001461}
1462
Jackal Guof9696682018-10-05 12:23:23 +08001463static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1464 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1465 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001466 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1467 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1468 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001469
1470 return args;
1471}
1472
chaviwd1c23182019-12-20 18:44:56 -08001473static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1474 const std::vector<PointF>& points) {
1475 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001476 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1477 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1478 }
1479
chaviwd1c23182019-12-20 18:44:56 -08001480 PointerProperties pointerProperties[pointerCount];
1481 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001482
chaviwd1c23182019-12-20 18:44:56 -08001483 for (size_t i = 0; i < pointerCount; i++) {
1484 pointerProperties[i].clear();
1485 pointerProperties[i].id = i;
1486 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001487
chaviwd1c23182019-12-20 18:44:56 -08001488 pointerCoords[i].clear();
1489 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1490 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1491 }
Jackal Guof9696682018-10-05 12:23:23 +08001492
1493 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1494 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001495 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001496 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1497 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001498 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1499 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001500 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1501 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001502
1503 return args;
1504}
1505
chaviwd1c23182019-12-20 18:44:56 -08001506static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1507 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1508}
1509
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001510static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1511 const PointerCaptureRequest& request) {
1512 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001513}
1514
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001515/**
1516 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1517 * broken channel.
1518 */
1519TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1521 sp<FakeWindowHandle> window =
1522 new FakeWindowHandle(application, mDispatcher, "Window that breaks its input channel",
1523 ADISPLAY_ID_DEFAULT);
1524
1525 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1526
1527 // Window closes its channel, but the window remains.
1528 window->destroyReceiver();
1529 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1530}
1531
Arthur Hungb92218b2018-08-14 12:00:21 +08001532TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001534 sp<FakeWindowHandle> window =
1535 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001536
Arthur Hung72d8dc32020-03-28 00:48:39 +00001537 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1539 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1540 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001541
1542 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001543 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001544}
1545
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001546TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1547 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1548 sp<FakeWindowHandle> window =
1549 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1550
1551 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1552 // Inject a MotionEvent to an unknown display.
1553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1554 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1555 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1556
1557 // Window should receive motion event.
1558 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1559}
1560
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001561/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001562 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001563 * This test serves as a sanity check for the next test, where setInputWindows is
1564 * called twice.
1565 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001566TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001568 sp<FakeWindowHandle> window =
1569 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1570 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001571
1572 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001574 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1575 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001576 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001577
1578 // Window should receive motion event.
1579 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1580}
1581
1582/**
1583 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001584 */
1585TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001586 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001587 sp<FakeWindowHandle> window =
1588 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1589 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001590
1591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001594 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1595 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001597
1598 // Window should receive motion event.
1599 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1600}
1601
Arthur Hungb92218b2018-08-14 12:00:21 +08001602// The foreground window should receive the first touch down event.
1603TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001605 sp<FakeWindowHandle> windowTop =
1606 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1607 sp<FakeWindowHandle> windowSecond =
1608 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001609
Arthur Hung72d8dc32020-03-28 00:48:39 +00001610 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1612 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001614
1615 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001616 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001617 windowSecond->assertNoEvents();
1618}
1619
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001620/**
1621 * Two windows: A top window, and a wallpaper behind the window.
1622 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1623 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001624 * 1. foregroundWindow <-- dup touch to wallpaper
1625 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001626 */
1627TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1628 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1629 sp<FakeWindowHandle> foregroundWindow =
1630 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001631 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001632 sp<FakeWindowHandle> wallpaperWindow =
1633 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001634 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001635 constexpr int expectedWallpaperFlags =
1636 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1637
1638 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1640 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1641 {100, 200}))
1642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1643
1644 // Both foreground window and its wallpaper should receive the touch down
1645 foregroundWindow->consumeMotionDown();
1646 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1647
1648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1649 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1650 ADISPLAY_ID_DEFAULT, {110, 200}))
1651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1652
1653 foregroundWindow->consumeMotionMove();
1654 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1655
1656 // Now the foreground window goes away, but the wallpaper stays
1657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1658 foregroundWindow->consumeMotionCancel();
1659 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1660 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1661}
1662
1663/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001664 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1665 * with the following differences:
1666 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1667 * clean up the connection.
1668 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1669 * Ensure that there's no crash in the dispatcher.
1670 */
1671TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1673 sp<FakeWindowHandle> foregroundWindow =
1674 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001675 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001676 sp<FakeWindowHandle> wallpaperWindow =
1677 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001678 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001679 constexpr int expectedWallpaperFlags =
1680 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1681
1682 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1684 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1685 {100, 200}))
1686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1687
1688 // Both foreground window and its wallpaper should receive the touch down
1689 foregroundWindow->consumeMotionDown();
1690 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1691
1692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1693 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1694 ADISPLAY_ID_DEFAULT, {110, 200}))
1695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1696
1697 foregroundWindow->consumeMotionMove();
1698 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1699
1700 // Wallpaper closes its channel, but the window remains.
1701 wallpaperWindow->destroyReceiver();
1702 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1703
1704 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1705 // is no longer valid.
1706 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1707 foregroundWindow->consumeMotionCancel();
1708}
1709
1710/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001711 * A single window that receives touch (on top), and a wallpaper window underneath it.
1712 * The top window gets a multitouch gesture.
1713 * Ensure that wallpaper gets the same gesture.
1714 */
1715TEST_F(InputDispatcherTest, WallpaperWindow_ReceivesMultiTouch) {
1716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1717 sp<FakeWindowHandle> window =
1718 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001719 window->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001720
1721 sp<FakeWindowHandle> wallpaperWindow =
1722 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001723 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001724 constexpr int expectedWallpaperFlags =
1725 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1726
1727 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1728
1729 // Touch down on top window
1730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1731 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1732 {100, 100}))
1733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1734
1735 // Both top window and its wallpaper should receive the touch down
1736 window->consumeMotionDown();
1737 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1738
1739 // Second finger down on the top window
1740 const MotionEvent secondFingerDownEvent =
1741 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1742 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1743 AINPUT_SOURCE_TOUCHSCREEN)
1744 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1745 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1746 .x(100)
1747 .y(100))
1748 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1749 .x(150)
1750 .y(150))
1751 .build();
1752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1753 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1754 InputEventInjectionSync::WAIT_FOR_RESULT))
1755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1756
1757 window->consumeMotionPointerDown(1 /* pointerIndex */);
1758 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1759 expectedWallpaperFlags);
1760 window->assertNoEvents();
1761 wallpaperWindow->assertNoEvents();
1762}
1763
1764/**
1765 * Two windows: a window on the left and window on the right.
1766 * A third window, wallpaper, is behind both windows, and spans both top windows.
1767 * The first touch down goes to the left window. A second pointer touches down on the right window.
1768 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1769 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1770 * ACTION_POINTER_DOWN(1).
1771 */
1772TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1773 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1774 sp<FakeWindowHandle> leftWindow =
1775 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1776 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001777 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001778
1779 sp<FakeWindowHandle> rightWindow =
1780 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1781 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001782 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001783
1784 sp<FakeWindowHandle> wallpaperWindow =
1785 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1786 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001787 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001788 constexpr int expectedWallpaperFlags =
1789 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1790
1791 mDispatcher->setInputWindows(
1792 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1793
1794 // Touch down on left window
1795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1796 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1797 {100, 100}))
1798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1799
1800 // Both foreground window and its wallpaper should receive the touch down
1801 leftWindow->consumeMotionDown();
1802 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1803
1804 // Second finger down on the right window
1805 const MotionEvent secondFingerDownEvent =
1806 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1807 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1808 AINPUT_SOURCE_TOUCHSCREEN)
1809 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1810 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1811 .x(100)
1812 .y(100))
1813 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1814 .x(300)
1815 .y(100))
1816 .build();
1817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1818 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1819 InputEventInjectionSync::WAIT_FOR_RESULT))
1820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1821
1822 leftWindow->consumeMotionMove();
1823 // Since the touch is split, right window gets ACTION_DOWN
1824 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1825 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1826 expectedWallpaperFlags);
1827
1828 // Now, leftWindow, which received the first finger, disappears.
1829 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1830 leftWindow->consumeMotionCancel();
1831 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1832 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1833
1834 // The pointer that's still down on the right window moves, and goes to the right window only.
1835 // As far as the dispatcher's concerned though, both pointers are still present.
1836 const MotionEvent secondFingerMoveEvent =
1837 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1838 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1839 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1840 .x(100)
1841 .y(100))
1842 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1843 .x(310)
1844 .y(110))
1845 .build();
1846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1847 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1848 InputEventInjectionSync::WAIT_FOR_RESULT));
1849 rightWindow->consumeMotionMove();
1850
1851 leftWindow->assertNoEvents();
1852 rightWindow->assertNoEvents();
1853 wallpaperWindow->assertNoEvents();
1854}
1855
Garfield Tandf26e862020-07-01 20:18:19 -07001856TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001858 sp<FakeWindowHandle> windowLeft =
1859 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1860 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07001861 sp<FakeWindowHandle> windowRight =
1862 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1863 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07001864
1865 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1866
1867 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1868
1869 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001871 injectMotionEvent(mDispatcher,
1872 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1873 AINPUT_SOURCE_MOUSE)
1874 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1875 .x(900)
1876 .y(400))
1877 .build()));
1878 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1879 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1880 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1881 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1882
1883 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001885 injectMotionEvent(mDispatcher,
1886 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1887 AINPUT_SOURCE_MOUSE)
1888 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1889 .x(300)
1890 .y(400))
1891 .build()));
1892 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1893 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1894 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1895 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1896 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1897 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1898
1899 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001901 injectMotionEvent(mDispatcher,
1902 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1903 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1904 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1905 .x(300)
1906 .y(400))
1907 .build()));
1908 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1909
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001911 injectMotionEvent(mDispatcher,
1912 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1913 AINPUT_SOURCE_MOUSE)
1914 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1915 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1916 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1917 .x(300)
1918 .y(400))
1919 .build()));
1920 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1921 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1922
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001924 injectMotionEvent(mDispatcher,
1925 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1926 AINPUT_SOURCE_MOUSE)
1927 .buttonState(0)
1928 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1929 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1930 .x(300)
1931 .y(400))
1932 .build()));
1933 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1934 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1935
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001937 injectMotionEvent(mDispatcher,
1938 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1939 .buttonState(0)
1940 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1941 .x(300)
1942 .y(400))
1943 .build()));
1944 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1945
1946 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001948 injectMotionEvent(mDispatcher,
1949 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1950 AINPUT_SOURCE_MOUSE)
1951 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1952 .x(900)
1953 .y(400))
1954 .build()));
1955 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1956 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1957 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1958 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1959 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1960 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1961}
1962
1963// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1964// directly in this test.
1965TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001966 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001967 sp<FakeWindowHandle> window =
1968 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1969 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07001970
1971 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1972
1973 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1974
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001976 injectMotionEvent(mDispatcher,
1977 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
1978 AINPUT_SOURCE_MOUSE)
1979 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1980 .x(300)
1981 .y(400))
1982 .build()));
1983 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1984 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1985
1986 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001988 injectMotionEvent(mDispatcher,
1989 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1990 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1991 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1992 .x(300)
1993 .y(400))
1994 .build()));
1995 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1996
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001998 injectMotionEvent(mDispatcher,
1999 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
2000 AINPUT_SOURCE_MOUSE)
2001 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2002 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2003 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2004 .x(300)
2005 .y(400))
2006 .build()));
2007 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
2008 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
2009
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002011 injectMotionEvent(mDispatcher,
2012 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2013 AINPUT_SOURCE_MOUSE)
2014 .buttonState(0)
2015 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2016 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2017 .x(300)
2018 .y(400))
2019 .build()));
2020 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2021 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
2022
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002024 injectMotionEvent(mDispatcher,
2025 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
2026 .buttonState(0)
2027 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2028 .x(300)
2029 .y(400))
2030 .build()));
2031 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002034 injectMotionEvent(mDispatcher,
2035 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
2036 AINPUT_SOURCE_MOUSE)
2037 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2038 .x(300)
2039 .y(400))
2040 .build()));
2041 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
2042 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
2043}
2044
Garfield Tan00f511d2019-06-12 16:55:40 -07002045TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07002046 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07002047
2048 sp<FakeWindowHandle> windowLeft =
2049 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2050 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07002051 sp<FakeWindowHandle> windowRight =
2052 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2053 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07002054
2055 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2056
Arthur Hung72d8dc32020-03-28 00:48:39 +00002057 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07002058
2059 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
2060 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07002062 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002063 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002064 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002065 windowRight->assertNoEvents();
2066}
2067
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002068TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002070 sp<FakeWindowHandle> window =
2071 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07002072 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002073
Arthur Hung72d8dc32020-03-28 00:48:39 +00002074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002075 setFocusedWindow(window);
2076
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002077 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002078
2079 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2080 mDispatcher->notifyKey(&keyArgs);
2081
2082 // Window should receive key down event.
2083 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2084
2085 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
2086 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002087 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002088 mDispatcher->notifyDeviceReset(&args);
2089 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2090 AKEY_EVENT_FLAG_CANCELED);
2091}
2092
2093TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002094 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002095 sp<FakeWindowHandle> window =
2096 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2097
Arthur Hung72d8dc32020-03-28 00:48:39 +00002098 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002099
2100 NotifyMotionArgs motionArgs =
2101 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2102 ADISPLAY_ID_DEFAULT);
2103 mDispatcher->notifyMotion(&motionArgs);
2104
2105 // Window should receive motion down event.
2106 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2107
2108 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
2109 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002110 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002111 mDispatcher->notifyDeviceReset(&args);
2112 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
2113 0 /*expectedFlags*/);
2114}
2115
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002116/**
2117 * Ensure the correct coordinate spaces are used by InputDispatcher.
2118 *
2119 * InputDispatcher works in the display space, so its coordinate system is relative to the display
2120 * panel. Windows get events in the window space, and get raw coordinates in the logical display
2121 * space.
2122 */
2123class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
2124public:
2125 void SetUp() override {
2126 InputDispatcherTest::SetUp();
2127 mDisplayInfos.clear();
2128 mWindowInfos.clear();
2129 }
2130
2131 void addDisplayInfo(int displayId, const ui::Transform& transform) {
2132 gui::DisplayInfo info;
2133 info.displayId = displayId;
2134 info.transform = transform;
2135 mDisplayInfos.push_back(std::move(info));
2136 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2137 }
2138
2139 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
2140 mWindowInfos.push_back(*windowHandle->getInfo());
2141 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2142 }
2143
2144 // Set up a test scenario where the display has a scaled projection and there are two windows
2145 // on the display.
2146 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
2147 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
2148 // respectively.
2149 ui::Transform displayTransform;
2150 displayTransform.set(2, 0, 0, 4);
2151 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
2152
2153 std::shared_ptr<FakeApplicationHandle> application =
2154 std::make_shared<FakeApplicationHandle>();
2155
2156 // Add two windows to the display. Their frames are represented in the display space.
2157 sp<FakeWindowHandle> firstWindow =
2158 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002159 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
2160 addWindow(firstWindow);
2161
2162 sp<FakeWindowHandle> secondWindow =
2163 new FakeWindowHandle(application, mDispatcher, "Second Window",
2164 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002165 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
2166 addWindow(secondWindow);
2167 return {std::move(firstWindow), std::move(secondWindow)};
2168 }
2169
2170private:
2171 std::vector<gui::DisplayInfo> mDisplayInfos;
2172 std::vector<gui::WindowInfo> mWindowInfos;
2173};
2174
2175TEST_F(InputDispatcherDisplayProjectionTest, HitTestsInDisplaySpace) {
2176 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2177 // Send down to the first window. The point is represented in the display space. The point is
2178 // selected so that if the hit test was done with the transform applied to it, then it would
2179 // end up in the incorrect window.
2180 NotifyMotionArgs downMotionArgs =
2181 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2182 ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
2183 mDispatcher->notifyMotion(&downMotionArgs);
2184
2185 firstWindow->consumeMotionDown();
2186 secondWindow->assertNoEvents();
2187}
2188
2189// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
2190// the event should be treated as being in the logical display space.
2191TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
2192 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2193 // Send down to the first window. The point is represented in the logical display space. The
2194 // point is selected so that if the hit test was done in logical display space, then it would
2195 // end up in the incorrect window.
2196 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2197 PointF{75 * 2, 55 * 4});
2198
2199 firstWindow->consumeMotionDown();
2200 secondWindow->assertNoEvents();
2201}
2202
Prabir Pradhandaa2f142021-12-10 09:30:08 +00002203// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
2204// event should be treated as being in the logical display space.
2205TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
2206 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2207
2208 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
2209 ui::Transform injectedEventTransform;
2210 injectedEventTransform.set(matrix);
2211 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
2212 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
2213
2214 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2215 .displayId(ADISPLAY_ID_DEFAULT)
2216 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2217 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2218 .x(untransformedPoint.x)
2219 .y(untransformedPoint.y))
2220 .build();
2221 event.transform(matrix);
2222
2223 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
2224 InputEventInjectionSync::WAIT_FOR_RESULT);
2225
2226 firstWindow->consumeMotionDown();
2227 secondWindow->assertNoEvents();
2228}
2229
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002230TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
2231 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2232
2233 // Send down to the second window.
2234 NotifyMotionArgs downMotionArgs =
2235 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2236 ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
2237 mDispatcher->notifyMotion(&downMotionArgs);
2238
2239 firstWindow->assertNoEvents();
2240 const MotionEvent* event = secondWindow->consumeMotion();
2241 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
2242
2243 // Ensure that the events from the "getRaw" API are in logical display coordinates.
2244 EXPECT_EQ(300, event->getRawX(0));
2245 EXPECT_EQ(880, event->getRawY(0));
2246
2247 // Ensure that the x and y values are in the window's coordinate space.
2248 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
2249 // the logical display space. This will be the origin of the window space.
2250 EXPECT_EQ(100, event->getX(0));
2251 EXPECT_EQ(80, event->getY(0));
2252}
2253
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002254using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
2255 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002256
2257class TransferTouchFixture : public InputDispatcherTest,
2258 public ::testing::WithParamInterface<TransferFunction> {};
2259
2260TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07002261 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002262
2263 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002264 sp<FakeWindowHandle> firstWindow =
2265 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2266 sp<FakeWindowHandle> secondWindow =
2267 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002268
2269 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002270 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002271
2272 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002273 NotifyMotionArgs downMotionArgs =
2274 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2275 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002276 mDispatcher->notifyMotion(&downMotionArgs);
2277 // Only the first window should get the down event
2278 firstWindow->consumeMotionDown();
2279 secondWindow->assertNoEvents();
2280
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002281 // Transfer touch to the second window
2282 TransferFunction f = GetParam();
2283 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2284 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002285 // The first window gets cancel and the second gets down
2286 firstWindow->consumeMotionCancel();
2287 secondWindow->consumeMotionDown();
2288
2289 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002290 NotifyMotionArgs upMotionArgs =
2291 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2292 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002293 mDispatcher->notifyMotion(&upMotionArgs);
2294 // The first window gets no events and the second gets up
2295 firstWindow->assertNoEvents();
2296 secondWindow->consumeMotionUp();
2297}
2298
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002299TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002301
2302 PointF touchPoint = {10, 10};
2303
2304 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002305 sp<FakeWindowHandle> firstWindow =
2306 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08002307 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002308 sp<FakeWindowHandle> secondWindow =
2309 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08002310 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002311
2312 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002313 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002314
2315 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002316 NotifyMotionArgs downMotionArgs =
2317 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2318 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002319 mDispatcher->notifyMotion(&downMotionArgs);
2320 // Only the first window should get the down event
2321 firstWindow->consumeMotionDown();
2322 secondWindow->assertNoEvents();
2323
2324 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002325 NotifyMotionArgs pointerDownMotionArgs =
2326 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2327 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2328 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2329 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002330 mDispatcher->notifyMotion(&pointerDownMotionArgs);
2331 // Only the first window should get the pointer down event
2332 firstWindow->consumeMotionPointerDown(1);
2333 secondWindow->assertNoEvents();
2334
2335 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002336 TransferFunction f = GetParam();
2337 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2338 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002339 // The first window gets cancel and the second gets down and pointer down
2340 firstWindow->consumeMotionCancel();
2341 secondWindow->consumeMotionDown();
2342 secondWindow->consumeMotionPointerDown(1);
2343
2344 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002345 NotifyMotionArgs pointerUpMotionArgs =
2346 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2347 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2348 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2349 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002350 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2351 // The first window gets nothing and the second gets pointer up
2352 firstWindow->assertNoEvents();
2353 secondWindow->consumeMotionPointerUp(1);
2354
2355 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002356 NotifyMotionArgs upMotionArgs =
2357 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2358 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002359 mDispatcher->notifyMotion(&upMotionArgs);
2360 // The first window gets nothing and the second gets up
2361 firstWindow->assertNoEvents();
2362 secondWindow->consumeMotionUp();
2363}
2364
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002365// For the cases of single pointer touch and two pointers non-split touch, the api's
2366// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
2367// for the case where there are multiple pointers split across several windows.
2368INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
2369 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002370 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
2371 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002372 return dispatcher->transferTouch(destChannelToken);
2373 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002374 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
2375 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002376 return dispatcher->transferTouchFocus(from, to,
2377 false /*isDragAndDrop*/);
2378 }));
2379
Svet Ganov5d3bc372020-01-26 23:11:07 -08002380TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002381 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002382
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002383 sp<FakeWindowHandle> firstWindow =
2384 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002385 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08002386
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002387 sp<FakeWindowHandle> secondWindow =
2388 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002389 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08002390
2391 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002392 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002393
2394 PointF pointInFirst = {300, 200};
2395 PointF pointInSecond = {300, 600};
2396
2397 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002398 NotifyMotionArgs firstDownMotionArgs =
2399 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2400 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002401 mDispatcher->notifyMotion(&firstDownMotionArgs);
2402 // Only the first window should get the down event
2403 firstWindow->consumeMotionDown();
2404 secondWindow->assertNoEvents();
2405
2406 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002407 NotifyMotionArgs secondDownMotionArgs =
2408 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2409 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2410 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2411 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002412 mDispatcher->notifyMotion(&secondDownMotionArgs);
2413 // The first window gets a move and the second a down
2414 firstWindow->consumeMotionMove();
2415 secondWindow->consumeMotionDown();
2416
2417 // Transfer touch focus to the second window
2418 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
2419 // The first window gets cancel and the new gets pointer down (it already saw down)
2420 firstWindow->consumeMotionCancel();
2421 secondWindow->consumeMotionPointerDown(1);
2422
2423 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002424 NotifyMotionArgs pointerUpMotionArgs =
2425 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2426 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2427 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2428 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002429 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2430 // The first window gets nothing and the second gets pointer up
2431 firstWindow->assertNoEvents();
2432 secondWindow->consumeMotionPointerUp(1);
2433
2434 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002435 NotifyMotionArgs upMotionArgs =
2436 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2437 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002438 mDispatcher->notifyMotion(&upMotionArgs);
2439 // The first window gets nothing and the second gets up
2440 firstWindow->assertNoEvents();
2441 secondWindow->consumeMotionUp();
2442}
2443
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002444// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
2445// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
2446// touch is not supported, so the touch should continue on those windows and the transferred-to
2447// window should get nothing.
2448TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
2449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2450
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002451 sp<FakeWindowHandle> firstWindow =
2452 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2453 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002454
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002455 sp<FakeWindowHandle> secondWindow =
2456 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2457 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002458
2459 // Add the windows to the dispatcher
2460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2461
2462 PointF pointInFirst = {300, 200};
2463 PointF pointInSecond = {300, 600};
2464
2465 // Send down to the first window
2466 NotifyMotionArgs firstDownMotionArgs =
2467 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2468 ADISPLAY_ID_DEFAULT, {pointInFirst});
2469 mDispatcher->notifyMotion(&firstDownMotionArgs);
2470 // Only the first window should get the down event
2471 firstWindow->consumeMotionDown();
2472 secondWindow->assertNoEvents();
2473
2474 // Send down to the second window
2475 NotifyMotionArgs secondDownMotionArgs =
2476 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2477 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2478 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2479 {pointInFirst, pointInSecond});
2480 mDispatcher->notifyMotion(&secondDownMotionArgs);
2481 // The first window gets a move and the second a down
2482 firstWindow->consumeMotionMove();
2483 secondWindow->consumeMotionDown();
2484
2485 // Transfer touch focus to the second window
2486 const bool transferred = mDispatcher->transferTouch(secondWindow->getToken());
2487 // The 'transferTouch' call should not succeed, because there are 2 touched windows
2488 ASSERT_FALSE(transferred);
2489 firstWindow->assertNoEvents();
2490 secondWindow->assertNoEvents();
2491
2492 // The rest of the dispatch should proceed as normal
2493 // Send pointer up to the second window
2494 NotifyMotionArgs pointerUpMotionArgs =
2495 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2496 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2497 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2498 {pointInFirst, pointInSecond});
2499 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2500 // The first window gets MOVE and the second gets pointer up
2501 firstWindow->consumeMotionMove();
2502 secondWindow->consumeMotionUp();
2503
2504 // Send up event to the first window
2505 NotifyMotionArgs upMotionArgs =
2506 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2507 ADISPLAY_ID_DEFAULT);
2508 mDispatcher->notifyMotion(&upMotionArgs);
2509 // The first window gets nothing and the second gets up
2510 firstWindow->consumeMotionUp();
2511 secondWindow->assertNoEvents();
2512}
2513
Arthur Hungabbb9d82021-09-01 14:52:30 +00002514// This case will create two windows and one mirrored window on the default display and mirror
2515// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
2516// the windows info of second display before default display.
2517TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
2518 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2519 sp<FakeWindowHandle> firstWindowInPrimary =
2520 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2521 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002522 sp<FakeWindowHandle> secondWindowInPrimary =
2523 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2524 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002525
2526 sp<FakeWindowHandle> mirrorWindowInPrimary =
2527 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2528 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002529
2530 sp<FakeWindowHandle> firstWindowInSecondary =
2531 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2532 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002533
2534 sp<FakeWindowHandle> secondWindowInSecondary =
2535 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2536 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002537
2538 // Update window info, let it find window handle of second display first.
2539 mDispatcher->setInputWindows(
2540 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2541 {ADISPLAY_ID_DEFAULT,
2542 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2543
2544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2545 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2546 {50, 50}))
2547 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2548
2549 // Window should receive motion event.
2550 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2551
2552 // Transfer touch focus
2553 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
2554 secondWindowInPrimary->getToken()));
2555 // The first window gets cancel.
2556 firstWindowInPrimary->consumeMotionCancel();
2557 secondWindowInPrimary->consumeMotionDown();
2558
2559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2560 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2561 ADISPLAY_ID_DEFAULT, {150, 50}))
2562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2563 firstWindowInPrimary->assertNoEvents();
2564 secondWindowInPrimary->consumeMotionMove();
2565
2566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2567 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2568 {150, 50}))
2569 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2570 firstWindowInPrimary->assertNoEvents();
2571 secondWindowInPrimary->consumeMotionUp();
2572}
2573
2574// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
2575// 'transferTouch' api.
2576TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
2577 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2578 sp<FakeWindowHandle> firstWindowInPrimary =
2579 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2580 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002581 sp<FakeWindowHandle> secondWindowInPrimary =
2582 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2583 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002584
2585 sp<FakeWindowHandle> mirrorWindowInPrimary =
2586 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2587 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002588
2589 sp<FakeWindowHandle> firstWindowInSecondary =
2590 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2591 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002592
2593 sp<FakeWindowHandle> secondWindowInSecondary =
2594 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2595 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00002596
2597 // Update window info, let it find window handle of second display first.
2598 mDispatcher->setInputWindows(
2599 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2600 {ADISPLAY_ID_DEFAULT,
2601 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2602
2603 // Touch on second display.
2604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2605 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
2606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2607
2608 // Window should receive motion event.
2609 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2610
2611 // Transfer touch focus
2612 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken()));
2613
2614 // The first window gets cancel.
2615 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
2616 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2617
2618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2619 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2620 SECOND_DISPLAY_ID, {150, 50}))
2621 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2622 firstWindowInPrimary->assertNoEvents();
2623 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
2624
2625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2626 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
2627 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2628 firstWindowInPrimary->assertNoEvents();
2629 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
2630}
2631
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002632TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002633 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002634 sp<FakeWindowHandle> window =
2635 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2636
Vishnu Nair47074b82020-08-14 11:54:47 -07002637 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002638 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002639 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002640
2641 window->consumeFocusEvent(true);
2642
2643 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2644 mDispatcher->notifyKey(&keyArgs);
2645
2646 // Window should receive key down event.
2647 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2648}
2649
2650TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002652 sp<FakeWindowHandle> window =
2653 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2654
Arthur Hung72d8dc32020-03-28 00:48:39 +00002655 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002656
2657 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2658 mDispatcher->notifyKey(&keyArgs);
2659 mDispatcher->waitForIdle();
2660
2661 window->assertNoEvents();
2662}
2663
2664// If a window is touchable, but does not have focus, it should receive motion events, but not keys
2665TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07002666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002667 sp<FakeWindowHandle> window =
2668 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2669
Arthur Hung72d8dc32020-03-28 00:48:39 +00002670 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002671
2672 // Send key
2673 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2674 mDispatcher->notifyKey(&keyArgs);
2675 // Send motion
2676 NotifyMotionArgs motionArgs =
2677 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2678 ADISPLAY_ID_DEFAULT);
2679 mDispatcher->notifyMotion(&motionArgs);
2680
2681 // Window should receive only the motion event
2682 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2683 window->assertNoEvents(); // Key event or focus event will not be received
2684}
2685
arthurhungea3f4fc2020-12-21 23:18:53 +08002686TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
2687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2688
arthurhungea3f4fc2020-12-21 23:18:53 +08002689 sp<FakeWindowHandle> firstWindow =
2690 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2691 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08002692
arthurhungea3f4fc2020-12-21 23:18:53 +08002693 sp<FakeWindowHandle> secondWindow =
2694 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2695 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08002696
2697 // Add the windows to the dispatcher
2698 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2699
2700 PointF pointInFirst = {300, 200};
2701 PointF pointInSecond = {300, 600};
2702
2703 // Send down to the first window
2704 NotifyMotionArgs firstDownMotionArgs =
2705 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2706 ADISPLAY_ID_DEFAULT, {pointInFirst});
2707 mDispatcher->notifyMotion(&firstDownMotionArgs);
2708 // Only the first window should get the down event
2709 firstWindow->consumeMotionDown();
2710 secondWindow->assertNoEvents();
2711
2712 // Send down to the second window
2713 NotifyMotionArgs secondDownMotionArgs =
2714 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2715 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2716 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2717 {pointInFirst, pointInSecond});
2718 mDispatcher->notifyMotion(&secondDownMotionArgs);
2719 // The first window gets a move and the second a down
2720 firstWindow->consumeMotionMove();
2721 secondWindow->consumeMotionDown();
2722
2723 // Send pointer cancel to the second window
2724 NotifyMotionArgs pointerUpMotionArgs =
2725 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2726 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2727 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2728 {pointInFirst, pointInSecond});
2729 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
2730 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2731 // The first window gets move and the second gets cancel.
2732 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2733 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2734
2735 // Send up event.
2736 NotifyMotionArgs upMotionArgs =
2737 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2738 ADISPLAY_ID_DEFAULT);
2739 mDispatcher->notifyMotion(&upMotionArgs);
2740 // The first window gets up and the second gets nothing.
2741 firstWindow->consumeMotionUp();
2742 secondWindow->assertNoEvents();
2743}
2744
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00002745TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
2746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2747
2748 sp<FakeWindowHandle> window =
2749 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2751 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
2752 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
2753 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
2754
2755 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
2756 window->assertNoEvents();
2757 mDispatcher->waitForIdle();
2758}
2759
chaviwd1c23182019-12-20 18:44:56 -08002760class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00002761public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002762 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002763 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07002764 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08002765 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07002766 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00002767 }
2768
chaviwd1c23182019-12-20 18:44:56 -08002769 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
2770
2771 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2772 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
2773 expectedDisplayId, expectedFlags);
2774 }
2775
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002776 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
2777
2778 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
2779
chaviwd1c23182019-12-20 18:44:56 -08002780 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2781 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
2782 expectedDisplayId, expectedFlags);
2783 }
2784
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002785 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2786 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
2787 expectedDisplayId, expectedFlags);
2788 }
2789
chaviwd1c23182019-12-20 18:44:56 -08002790 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2791 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
2792 expectedDisplayId, expectedFlags);
2793 }
2794
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002795 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2796 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2797 expectedDisplayId, expectedFlags);
2798 }
2799
Arthur Hungfbfa5722021-11-16 02:45:54 +00002800 void consumeMotionPointerDown(int32_t pointerIdx) {
2801 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
2802 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2803 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
2804 0 /*expectedFlags*/);
2805 }
2806
Evan Rosky84f07f02021-04-16 10:42:42 -07002807 MotionEvent* consumeMotion() {
2808 InputEvent* event = mInputReceiver->consume();
2809 if (!event) {
2810 ADD_FAILURE() << "No event was produced";
2811 return nullptr;
2812 }
2813 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
2814 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
2815 return nullptr;
2816 }
2817 return static_cast<MotionEvent*>(event);
2818 }
2819
chaviwd1c23182019-12-20 18:44:56 -08002820 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
2821
2822private:
2823 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00002824};
2825
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002826using InputDispatcherMonitorTest = InputDispatcherTest;
2827
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002828/**
2829 * Two entities that receive touch: A window, and a global monitor.
2830 * The touch goes to the window, and then the window disappears.
2831 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
2832 * for the monitor, as well.
2833 * 1. foregroundWindow
2834 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
2835 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002836TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002837 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2838 sp<FakeWindowHandle> window =
2839 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2840
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002841 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002842
2843 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2845 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2846 {100, 200}))
2847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2848
2849 // Both the foreground window and the global monitor should receive the touch down
2850 window->consumeMotionDown();
2851 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2852
2853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2854 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2855 ADISPLAY_ID_DEFAULT, {110, 200}))
2856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2857
2858 window->consumeMotionMove();
2859 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
2860
2861 // Now the foreground window goes away
2862 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2863 window->consumeMotionCancel();
2864 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
2865
2866 // If more events come in, there will be no more foreground window to send them to. This will
2867 // cause a cancel for the monitor, as well.
2868 ASSERT_EQ(InputEventInjectionResult::FAILED,
2869 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2870 ADISPLAY_ID_DEFAULT, {120, 200}))
2871 << "Injection should fail because the window was removed";
2872 window->assertNoEvents();
2873 // Global monitor now gets the cancel
2874 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
2875}
2876
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002877TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002878 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002879 sp<FakeWindowHandle> window =
2880 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002881 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002882
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002883 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002884
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002886 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002888 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002889 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002890}
2891
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002892TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
2893 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002894
Chris Yea209fde2020-07-22 13:54:51 -07002895 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002896 sp<FakeWindowHandle> window =
2897 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002899
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002901 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002902 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08002903 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002904 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002905
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002906 // Pilfer pointers from the monitor.
2907 // This should not do anything and the window should continue to receive events.
2908 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00002909
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002911 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2912 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002914
2915 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
2916 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002917}
2918
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002919TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07002920 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2921 sp<FakeWindowHandle> window =
2922 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2923 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2924 window->setWindowOffset(20, 40);
2925 window->setWindowTransform(0, 1, -1, 0);
2926
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002927 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07002928
2929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2930 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2932 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2933 MotionEvent* event = monitor.consumeMotion();
2934 // Even though window has transform, gesture monitor must not.
2935 ASSERT_EQ(ui::Transform(), event->getTransform());
2936}
2937
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002938TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00002939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002940 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00002941
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002942 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00002943 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002944 << "Injection should fail if there is a monitor, but no touchable window";
2945 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00002946}
2947
chaviw81e2bb92019-12-18 15:03:51 -08002948TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002949 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08002950 sp<FakeWindowHandle> window =
2951 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2952
Arthur Hung72d8dc32020-03-28 00:48:39 +00002953 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08002954
2955 NotifyMotionArgs motionArgs =
2956 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2957 ADISPLAY_ID_DEFAULT);
2958
2959 mDispatcher->notifyMotion(&motionArgs);
2960 // Window should receive motion down event.
2961 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2962
2963 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002964 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08002965 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2966 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
2967 motionArgs.pointerCoords[0].getX() - 10);
2968
2969 mDispatcher->notifyMotion(&motionArgs);
2970 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
2971 0 /*expectedFlags*/);
2972}
2973
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002974/**
2975 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
2976 * the device default right away. In the test scenario, we check both the default value,
2977 * and the action of enabling / disabling.
2978 */
2979TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07002980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002981 sp<FakeWindowHandle> window =
2982 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08002983 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002984
2985 // Set focused application.
2986 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07002987 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002988
2989 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00002990 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002991 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002992 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
2993
2994 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07002995 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002997 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
2998
2999 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003000 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
3001 /* hasPermission */ true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003002 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07003003 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003004 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003005 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003006 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
3007
3008 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003009 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003010 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003011 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
3012
3013 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003014 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
3015 /* hasPermission */ true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003016 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07003017 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003018 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003019 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003020 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3021
3022 window->assertNoEvents();
3023}
3024
Gang Wange9087892020-01-07 12:17:14 -05003025TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003026 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05003027 sp<FakeWindowHandle> window =
3028 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
3029
3030 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003031 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05003032
Arthur Hung72d8dc32020-03-28 00:48:39 +00003033 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003034 setFocusedWindow(window);
3035
Gang Wange9087892020-01-07 12:17:14 -05003036 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3037
3038 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3039 mDispatcher->notifyKey(&keyArgs);
3040
3041 InputEvent* event = window->consume();
3042 ASSERT_NE(event, nullptr);
3043
3044 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3045 ASSERT_NE(verified, nullptr);
3046 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
3047
3048 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
3049 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
3050 ASSERT_EQ(keyArgs.source, verified->source);
3051 ASSERT_EQ(keyArgs.displayId, verified->displayId);
3052
3053 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
3054
3055 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05003056 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003057 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05003058 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
3059 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
3060 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
3061 ASSERT_EQ(0, verifiedKey.repeatCount);
3062}
3063
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003064TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003065 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003066 sp<FakeWindowHandle> window =
3067 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
3068
3069 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3070
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003071 ui::Transform transform;
3072 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3073
3074 gui::DisplayInfo displayInfo;
3075 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
3076 displayInfo.transform = transform;
3077
3078 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003079
3080 NotifyMotionArgs motionArgs =
3081 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3082 ADISPLAY_ID_DEFAULT);
3083 mDispatcher->notifyMotion(&motionArgs);
3084
3085 InputEvent* event = window->consume();
3086 ASSERT_NE(event, nullptr);
3087
3088 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3089 ASSERT_NE(verified, nullptr);
3090 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
3091
3092 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
3093 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
3094 EXPECT_EQ(motionArgs.source, verified->source);
3095 EXPECT_EQ(motionArgs.displayId, verified->displayId);
3096
3097 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
3098
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003099 const vec2 rawXY =
3100 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
3101 motionArgs.pointerCoords[0].getXYValue());
3102 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
3103 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003104 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003105 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003106 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003107 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
3108 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
3109}
3110
chaviw09c8d2d2020-08-24 15:48:26 -07003111/**
3112 * Ensure that separate calls to sign the same data are generating the same key.
3113 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
3114 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
3115 * tests.
3116 */
3117TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
3118 KeyEvent event = getTestKeyEvent();
3119 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
3120
3121 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
3122 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
3123 ASSERT_EQ(hmac1, hmac2);
3124}
3125
3126/**
3127 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
3128 */
3129TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
3130 KeyEvent event = getTestKeyEvent();
3131 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
3132 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
3133
3134 verifiedEvent.deviceId += 1;
3135 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3136
3137 verifiedEvent.source += 1;
3138 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3139
3140 verifiedEvent.eventTimeNanos += 1;
3141 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3142
3143 verifiedEvent.displayId += 1;
3144 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3145
3146 verifiedEvent.action += 1;
3147 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3148
3149 verifiedEvent.downTimeNanos += 1;
3150 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3151
3152 verifiedEvent.flags += 1;
3153 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3154
3155 verifiedEvent.keyCode += 1;
3156 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3157
3158 verifiedEvent.scanCode += 1;
3159 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3160
3161 verifiedEvent.metaState += 1;
3162 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3163
3164 verifiedEvent.repeatCount += 1;
3165 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3166}
3167
Vishnu Nair958da932020-08-21 17:12:37 -07003168TEST_F(InputDispatcherTest, SetFocusedWindow) {
3169 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3170 sp<FakeWindowHandle> windowTop =
3171 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3172 sp<FakeWindowHandle> windowSecond =
3173 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3174 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3175
3176 // Top window is also focusable but is not granted focus.
3177 windowTop->setFocusable(true);
3178 windowSecond->setFocusable(true);
3179 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3180 setFocusedWindow(windowSecond);
3181
3182 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3184 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003185
3186 // Focused window should receive event.
3187 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3188 windowTop->assertNoEvents();
3189}
3190
3191TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
3192 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3193 sp<FakeWindowHandle> window =
3194 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3195 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3196
3197 window->setFocusable(true);
3198 // Release channel for window is no longer valid.
3199 window->releaseChannel();
3200 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3201 setFocusedWindow(window);
3202
3203 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003204 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3205 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003206
3207 // window channel is invalid, so it should not receive any input event.
3208 window->assertNoEvents();
3209}
3210
3211TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
3212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3213 sp<FakeWindowHandle> window =
3214 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08003215 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07003216 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3217
Vishnu Nair958da932020-08-21 17:12:37 -07003218 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3219 setFocusedWindow(window);
3220
3221 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003222 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3223 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003224
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08003225 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07003226 window->assertNoEvents();
3227}
3228
3229TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
3230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3231 sp<FakeWindowHandle> windowTop =
3232 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3233 sp<FakeWindowHandle> windowSecond =
3234 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3235 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3236
3237 windowTop->setFocusable(true);
3238 windowSecond->setFocusable(true);
3239 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3240 setFocusedWindow(windowTop);
3241 windowTop->consumeFocusEvent(true);
3242
3243 setFocusedWindow(windowSecond, windowTop);
3244 windowSecond->consumeFocusEvent(true);
3245 windowTop->consumeFocusEvent(false);
3246
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3248 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003249
3250 // Focused window should receive event.
3251 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3252}
3253
3254TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
3255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3256 sp<FakeWindowHandle> windowTop =
3257 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3258 sp<FakeWindowHandle> windowSecond =
3259 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3260 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3261
3262 windowTop->setFocusable(true);
3263 windowSecond->setFocusable(true);
3264 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3265 setFocusedWindow(windowSecond, windowTop);
3266
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003267 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3268 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003269
3270 // Event should be dropped.
3271 windowTop->assertNoEvents();
3272 windowSecond->assertNoEvents();
3273}
3274
3275TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
3276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3277 sp<FakeWindowHandle> window =
3278 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3279 sp<FakeWindowHandle> previousFocusedWindow =
3280 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
3281 ADISPLAY_ID_DEFAULT);
3282 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3283
3284 window->setFocusable(true);
3285 previousFocusedWindow->setFocusable(true);
3286 window->setVisible(false);
3287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
3288 setFocusedWindow(previousFocusedWindow);
3289 previousFocusedWindow->consumeFocusEvent(true);
3290
3291 // Requesting focus on invisible window takes focus from currently focused window.
3292 setFocusedWindow(window);
3293 previousFocusedWindow->consumeFocusEvent(false);
3294
3295 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003297 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003298 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003299
3300 // Window does not get focus event or key down.
3301 window->assertNoEvents();
3302
3303 // Window becomes visible.
3304 window->setVisible(true);
3305 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3306
3307 // Window receives focus event.
3308 window->consumeFocusEvent(true);
3309 // Focused window receives key down.
3310 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3311}
3312
Vishnu Nair599f1412021-06-21 10:39:58 -07003313TEST_F(InputDispatcherTest, DisplayRemoved) {
3314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3315 sp<FakeWindowHandle> window =
3316 new FakeWindowHandle(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
3317 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3318
3319 // window is granted focus.
3320 window->setFocusable(true);
3321 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3322 setFocusedWindow(window);
3323 window->consumeFocusEvent(true);
3324
3325 // When a display is removed window loses focus.
3326 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
3327 window->consumeFocusEvent(false);
3328}
3329
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003330/**
3331 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
3332 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
3333 * of the 'slipperyEnterWindow'.
3334 *
3335 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
3336 * a way so that the touched location is no longer covered by the top window.
3337 *
3338 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
3339 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
3340 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
3341 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
3342 * with ACTION_DOWN).
3343 * Thus, the touch has been transferred from the top window into the bottom window, because the top
3344 * window moved itself away from the touched location and had Flag::SLIPPERY.
3345 *
3346 * Even though the top window moved away from the touched location, it is still obscuring the bottom
3347 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
3348 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
3349 *
3350 * In this test, we ensure that the event received by the bottom window has
3351 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
3352 */
3353TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
3354 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
3355 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
3356
3357 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3358 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3359
3360 sp<FakeWindowHandle> slipperyExitWindow =
3361 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08003362 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003363 // Make sure this one overlaps the bottom window
3364 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
3365 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
3366 // one. Windows with the same owner are not considered to be occluding each other.
3367 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
3368
3369 sp<FakeWindowHandle> slipperyEnterWindow =
3370 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3371 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
3372
3373 mDispatcher->setInputWindows(
3374 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3375
3376 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
3377 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3378 ADISPLAY_ID_DEFAULT, {{50, 50}});
3379 mDispatcher->notifyMotion(&args);
3380 slipperyExitWindow->consumeMotionDown();
3381 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
3382 mDispatcher->setInputWindows(
3383 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3384
3385 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3386 ADISPLAY_ID_DEFAULT, {{51, 51}});
3387 mDispatcher->notifyMotion(&args);
3388
3389 slipperyExitWindow->consumeMotionCancel();
3390
3391 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
3392 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
3393}
3394
Garfield Tan1c7bc862020-01-28 13:24:04 -08003395class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
3396protected:
3397 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
3398 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
3399
Chris Yea209fde2020-07-22 13:54:51 -07003400 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003401 sp<FakeWindowHandle> mWindow;
3402
3403 virtual void SetUp() override {
3404 mFakePolicy = new FakeInputDispatcherPolicy();
3405 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003406 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003407 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
3408 ASSERT_EQ(OK, mDispatcher->start());
3409
3410 setUpWindow();
3411 }
3412
3413 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07003414 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08003415 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
3416
Vishnu Nair47074b82020-08-14 11:54:47 -07003417 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003418 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003419 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003420 mWindow->consumeFocusEvent(true);
3421 }
3422
Chris Ye2ad95392020-09-01 13:44:44 -07003423 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003424 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003425 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003426 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
3427 mDispatcher->notifyKey(&keyArgs);
3428
3429 // Window should receive key down event.
3430 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3431 }
3432
3433 void expectKeyRepeatOnce(int32_t repeatCount) {
3434 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
3435 InputEvent* repeatEvent = mWindow->consume();
3436 ASSERT_NE(nullptr, repeatEvent);
3437
3438 uint32_t eventType = repeatEvent->getType();
3439 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
3440
3441 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
3442 uint32_t eventAction = repeatKeyEvent->getAction();
3443 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
3444 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
3445 }
3446
Chris Ye2ad95392020-09-01 13:44:44 -07003447 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003448 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003449 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003450 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
3451 mDispatcher->notifyKey(&keyArgs);
3452
3453 // Window should receive key down event.
3454 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
3455 0 /*expectedFlags*/);
3456 }
3457};
3458
3459TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07003460 sendAndConsumeKeyDown(1 /* deviceId */);
3461 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3462 expectKeyRepeatOnce(repeatCount);
3463 }
3464}
3465
3466TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
3467 sendAndConsumeKeyDown(1 /* deviceId */);
3468 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3469 expectKeyRepeatOnce(repeatCount);
3470 }
3471 sendAndConsumeKeyDown(2 /* deviceId */);
3472 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08003473 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3474 expectKeyRepeatOnce(repeatCount);
3475 }
3476}
3477
3478TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07003479 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003480 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07003481 sendAndConsumeKeyUp(1 /* deviceId */);
3482 mWindow->assertNoEvents();
3483}
3484
3485TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
3486 sendAndConsumeKeyDown(1 /* deviceId */);
3487 expectKeyRepeatOnce(1 /*repeatCount*/);
3488 sendAndConsumeKeyDown(2 /* deviceId */);
3489 expectKeyRepeatOnce(1 /*repeatCount*/);
3490 // Stale key up from device 1.
3491 sendAndConsumeKeyUp(1 /* deviceId */);
3492 // Device 2 is still down, keep repeating
3493 expectKeyRepeatOnce(2 /*repeatCount*/);
3494 expectKeyRepeatOnce(3 /*repeatCount*/);
3495 // Device 2 key up
3496 sendAndConsumeKeyUp(2 /* deviceId */);
3497 mWindow->assertNoEvents();
3498}
3499
3500TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
3501 sendAndConsumeKeyDown(1 /* deviceId */);
3502 expectKeyRepeatOnce(1 /*repeatCount*/);
3503 sendAndConsumeKeyDown(2 /* deviceId */);
3504 expectKeyRepeatOnce(1 /*repeatCount*/);
3505 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
3506 sendAndConsumeKeyUp(2 /* deviceId */);
3507 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08003508 mWindow->assertNoEvents();
3509}
3510
liushenxiang42232912021-05-21 20:24:09 +08003511TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
3512 sendAndConsumeKeyDown(DEVICE_ID);
3513 expectKeyRepeatOnce(1 /*repeatCount*/);
3514 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
3515 mDispatcher->notifyDeviceReset(&args);
3516 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
3517 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
3518 mWindow->assertNoEvents();
3519}
3520
Garfield Tan1c7bc862020-01-28 13:24:04 -08003521TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07003522 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003523 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3524 InputEvent* repeatEvent = mWindow->consume();
3525 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3526 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
3527 IdGenerator::getSource(repeatEvent->getId()));
3528 }
3529}
3530
3531TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07003532 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003533
3534 std::unordered_set<int32_t> idSet;
3535 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3536 InputEvent* repeatEvent = mWindow->consume();
3537 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3538 int32_t id = repeatEvent->getId();
3539 EXPECT_EQ(idSet.end(), idSet.find(id));
3540 idSet.insert(id);
3541 }
3542}
3543
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003544/* Test InputDispatcher for MultiDisplay */
3545class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
3546public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003547 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003548 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08003549
Chris Yea209fde2020-07-22 13:54:51 -07003550 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003551 windowInPrimary =
3552 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003553
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003554 // Set focus window for primary display, but focused display would be second one.
3555 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07003556 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003557 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003558 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003559 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08003560
Chris Yea209fde2020-07-22 13:54:51 -07003561 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003562 windowInSecondary =
3563 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003564 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003565 // Set focus display to second one.
3566 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
3567 // Set focus window for second display.
3568 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07003569 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003570 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003571 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003572 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003573 }
3574
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003575 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003576 InputDispatcherTest::TearDown();
3577
Chris Yea209fde2020-07-22 13:54:51 -07003578 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003579 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07003580 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003581 windowInSecondary.clear();
3582 }
3583
3584protected:
Chris Yea209fde2020-07-22 13:54:51 -07003585 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003586 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07003587 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003588 sp<FakeWindowHandle> windowInSecondary;
3589};
3590
3591TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
3592 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3594 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003596 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08003597 windowInSecondary->assertNoEvents();
3598
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003599 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3601 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3602 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003603 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003604 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08003605}
3606
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003607TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08003608 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3610 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003611 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003612 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08003613 windowInSecondary->assertNoEvents();
3614
3615 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003617 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003618 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003619 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08003620
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003621 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003622 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08003623
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003624 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003625 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
3626 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08003627
3628 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003629 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003630 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08003631 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003632 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08003633 windowInSecondary->assertNoEvents();
3634}
3635
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003636// Test per-display input monitors for motion event.
3637TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08003638 FakeMonitorReceiver monitorInPrimary =
3639 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3640 FakeMonitorReceiver monitorInSecondary =
3641 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003642
3643 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3645 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3646 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003647 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003648 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003649 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003650 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003651
3652 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3654 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003656 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003657 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003658 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08003659 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003660
3661 // Test inject a non-pointer motion event.
3662 // If specific a display, it will dispatch to the focused window of particular display,
3663 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3665 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
3666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003667 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003668 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003669 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003670 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003671}
3672
3673// Test per-display input monitors for key event.
3674TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003675 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08003676 FakeMonitorReceiver monitorInPrimary =
3677 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3678 FakeMonitorReceiver monitorInSecondary =
3679 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003680
3681 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3683 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003684 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003685 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003686 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003687 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003688}
3689
Vishnu Nair958da932020-08-21 17:12:37 -07003690TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
3691 sp<FakeWindowHandle> secondWindowInPrimary =
3692 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
3693 secondWindowInPrimary->setFocusable(true);
3694 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
3695 setFocusedWindow(secondWindowInPrimary);
3696 windowInPrimary->consumeFocusEvent(false);
3697 secondWindowInPrimary->consumeFocusEvent(true);
3698
3699 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
3701 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003702 windowInPrimary->assertNoEvents();
3703 windowInSecondary->assertNoEvents();
3704 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3705}
3706
Arthur Hungdfd528e2021-12-08 13:23:04 +00003707TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
3708 FakeMonitorReceiver monitorInPrimary =
3709 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3710 FakeMonitorReceiver monitorInSecondary =
3711 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
3712
3713 // Test touch down on primary display.
3714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3715 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3716 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3717 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3718 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3719
3720 // Test touch down on second display.
3721 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3722 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3724 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
3725 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
3726
3727 // Trigger cancel touch.
3728 mDispatcher->cancelCurrentTouch();
3729 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
3730 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
3731 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
3732 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
3733
3734 // Test inject a move motion event, no window/monitor should receive the event.
3735 ASSERT_EQ(InputEventInjectionResult::FAILED,
3736 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3737 ADISPLAY_ID_DEFAULT, {110, 200}))
3738 << "Inject motion event should return InputEventInjectionResult::FAILED";
3739 windowInPrimary->assertNoEvents();
3740 monitorInPrimary.assertNoEvents();
3741
3742 ASSERT_EQ(InputEventInjectionResult::FAILED,
3743 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3744 SECOND_DISPLAY_ID, {110, 200}))
3745 << "Inject motion event should return InputEventInjectionResult::FAILED";
3746 windowInSecondary->assertNoEvents();
3747 monitorInSecondary.assertNoEvents();
3748}
3749
Jackal Guof9696682018-10-05 12:23:23 +08003750class InputFilterTest : public InputDispatcherTest {
3751protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003752 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
3753 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08003754 NotifyMotionArgs motionArgs;
3755
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003756 motionArgs =
3757 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003758 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003759 motionArgs =
3760 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003761 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003762 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003763 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003764 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
3765 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08003766 } else {
3767 mFakePolicy->assertFilterInputEventWasNotCalled();
3768 }
3769 }
3770
3771 void testNotifyKey(bool expectToBeFiltered) {
3772 NotifyKeyArgs keyArgs;
3773
3774 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3775 mDispatcher->notifyKey(&keyArgs);
3776 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
3777 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003778 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003779
3780 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003781 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003782 } else {
3783 mFakePolicy->assertFilterInputEventWasNotCalled();
3784 }
3785 }
3786};
3787
3788// Test InputFilter for MotionEvent
3789TEST_F(InputFilterTest, MotionEvent_InputFilter) {
3790 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
3791 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3792 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3793
3794 // Enable InputFilter
3795 mDispatcher->setInputFilterEnabled(true);
3796 // Test touch on both primary and second display, and check if both events are filtered.
3797 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
3798 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
3799
3800 // Disable InputFilter
3801 mDispatcher->setInputFilterEnabled(false);
3802 // Test touch on both primary and second display, and check if both events aren't filtered.
3803 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3804 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3805}
3806
3807// Test InputFilter for KeyEvent
3808TEST_F(InputFilterTest, KeyEvent_InputFilter) {
3809 // Since the InputFilter is disabled by default, check if key event aren't filtered.
3810 testNotifyKey(/*expectToBeFiltered*/ false);
3811
3812 // Enable InputFilter
3813 mDispatcher->setInputFilterEnabled(true);
3814 // Send a key event, and check if it is filtered.
3815 testNotifyKey(/*expectToBeFiltered*/ true);
3816
3817 // Disable InputFilter
3818 mDispatcher->setInputFilterEnabled(false);
3819 // Send a key event, and check if it isn't filtered.
3820 testNotifyKey(/*expectToBeFiltered*/ false);
3821}
3822
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003823// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
3824// logical display coordinate space.
3825TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
3826 ui::Transform firstDisplayTransform;
3827 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3828 ui::Transform secondDisplayTransform;
3829 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
3830
3831 std::vector<gui::DisplayInfo> displayInfos(2);
3832 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
3833 displayInfos[0].transform = firstDisplayTransform;
3834 displayInfos[1].displayId = SECOND_DISPLAY_ID;
3835 displayInfos[1].transform = secondDisplayTransform;
3836
3837 mDispatcher->onWindowInfosChanged({}, displayInfos);
3838
3839 // Enable InputFilter
3840 mDispatcher->setInputFilterEnabled(true);
3841
3842 // Ensure the correct transforms are used for the displays.
3843 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
3844 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
3845}
3846
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003847class InputFilterInjectionPolicyTest : public InputDispatcherTest {
3848protected:
3849 virtual void SetUp() override {
3850 InputDispatcherTest::SetUp();
3851
3852 /**
3853 * We don't need to enable input filter to test the injected event policy, but we enabled it
3854 * here to make the tests more realistic, since this policy only matters when inputfilter is
3855 * on.
3856 */
3857 mDispatcher->setInputFilterEnabled(true);
3858
3859 std::shared_ptr<InputApplicationHandle> application =
3860 std::make_shared<FakeApplicationHandle>();
3861 mWindow =
3862 new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT);
3863
3864 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3865 mWindow->setFocusable(true);
3866 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3867 setFocusedWindow(mWindow);
3868 mWindow->consumeFocusEvent(true);
3869 }
3870
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003871 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3872 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003873 KeyEvent event;
3874
3875 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3876 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
3877 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
3878 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
3879 const int32_t additionalPolicyFlags =
3880 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
3881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3882 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3883 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3884 policyFlags | additionalPolicyFlags));
3885
3886 InputEvent* received = mWindow->consume();
3887 ASSERT_NE(nullptr, received);
3888 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003889 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
3890 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
3891 ASSERT_EQ(flags, keyEvent.getFlags());
3892 }
3893
3894 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3895 int32_t flags) {
3896 MotionEvent event;
3897 PointerProperties pointerProperties[1];
3898 PointerCoords pointerCoords[1];
3899 pointerProperties[0].clear();
3900 pointerProperties[0].id = 0;
3901 pointerCoords[0].clear();
3902 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
3903 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
3904
3905 ui::Transform identityTransform;
3906 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3907 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
3908 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
3909 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
3910 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07003911 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07003912 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003913 /*pointerCount*/ 1, pointerProperties, pointerCoords);
3914
3915 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
3916 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3917 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3918 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3919 policyFlags | additionalPolicyFlags));
3920
3921 InputEvent* received = mWindow->consume();
3922 ASSERT_NE(nullptr, received);
3923 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
3924 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
3925 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
3926 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003927 }
3928
3929private:
3930 sp<FakeWindowHandle> mWindow;
3931};
3932
3933TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003934 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
3935 // filter. Without it, the event will no different from a regularly injected event, and the
3936 // injected device id will be overwritten.
3937 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3938 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003939}
3940
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003941TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003942 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003943 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3944 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3945}
3946
3947TEST_F(InputFilterInjectionPolicyTest,
3948 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
3949 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
3950 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3951 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003952}
3953
3954TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
3955 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003956 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003957}
3958
chaviwfd6d3512019-03-25 13:23:49 -07003959class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003960 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07003961 InputDispatcherTest::SetUp();
3962
Chris Yea209fde2020-07-22 13:54:51 -07003963 std::shared_ptr<FakeApplicationHandle> application =
3964 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003965 mUnfocusedWindow =
3966 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07003967 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07003968
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003969 mFocusedWindow =
3970 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3971 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07003972
3973 // Set focused application.
3974 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003975 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07003976
3977 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003978 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003979 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003980 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07003981 }
3982
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003983 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07003984 InputDispatcherTest::TearDown();
3985
3986 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003987 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07003988 }
3989
3990protected:
3991 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003992 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07003993 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07003994};
3995
3996// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
3997// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
3998// the onPointerDownOutsideFocus callback.
3999TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004001 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4002 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004004 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004005
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004006 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07004007 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
4008}
4009
4010// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
4011// DOWN on the window that doesn't have focus. Ensure no window received the
4012// onPointerDownOutsideFocus callback.
4013TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004015 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004017 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004018
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004019 ASSERT_TRUE(mDispatcher->waitForIdle());
4020 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004021}
4022
4023// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
4024// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
4025TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4027 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004028 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004029 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004030
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004031 ASSERT_TRUE(mDispatcher->waitForIdle());
4032 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004033}
4034
4035// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4036// DOWN on the window that already has focus. Ensure no window received the
4037// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004038TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004040 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004041 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004043 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004044
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004045 ASSERT_TRUE(mDispatcher->waitForIdle());
4046 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004047}
4048
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08004049// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
4050// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
4051TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
4052 const MotionEvent event =
4053 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4054 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
4055 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
4056 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
4057 .build();
4058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
4059 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4060 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
4061
4062 ASSERT_TRUE(mDispatcher->waitForIdle());
4063 mFakePolicy->assertOnPointerDownWasNotCalled();
4064 // Ensure that the unfocused window did not receive any FOCUS events.
4065 mUnfocusedWindow->assertNoEvents();
4066}
4067
chaviwaf87b3e2019-10-01 16:59:28 -07004068// These tests ensures we can send touch events to a single client when there are multiple input
4069// windows that point to the same client token.
4070class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
4071 virtual void SetUp() override {
4072 InputDispatcherTest::SetUp();
4073
Chris Yea209fde2020-07-22 13:54:51 -07004074 std::shared_ptr<FakeApplicationHandle> application =
4075 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07004076 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
4077 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07004078 mWindow1->setFrame(Rect(0, 0, 100, 100));
4079
4080 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
4081 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07004082 mWindow2->setFrame(Rect(100, 100, 200, 200));
4083
Arthur Hung72d8dc32020-03-28 00:48:39 +00004084 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07004085 }
4086
4087protected:
4088 sp<FakeWindowHandle> mWindow1;
4089 sp<FakeWindowHandle> mWindow2;
4090
4091 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05004092 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07004093 vec2 vals = windowInfo->transform.transform(point.x, point.y);
4094 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07004095 }
4096
4097 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
4098 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004099 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07004100 InputEvent* event = window->consume();
4101
4102 ASSERT_NE(nullptr, event) << name.c_str()
4103 << ": consumer should have returned non-NULL event.";
4104
4105 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
4106 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
4107 << " event, got " << inputEventTypeToString(event->getType()) << " event";
4108
4109 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004110 assertMotionAction(expectedAction, motionEvent.getAction());
chaviwaf87b3e2019-10-01 16:59:28 -07004111
4112 for (size_t i = 0; i < points.size(); i++) {
4113 float expectedX = points[i].x;
4114 float expectedY = points[i].y;
4115
4116 EXPECT_EQ(expectedX, motionEvent.getX(i))
4117 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
4118 << ", got " << motionEvent.getX(i);
4119 EXPECT_EQ(expectedY, motionEvent.getY(i))
4120 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
4121 << ", got " << motionEvent.getY(i);
4122 }
4123 }
chaviw9eaa22c2020-07-01 16:21:27 -07004124
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004125 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07004126 std::vector<PointF> expectedPoints) {
4127 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
4128 ADISPLAY_ID_DEFAULT, touchedPoints);
4129 mDispatcher->notifyMotion(&motionArgs);
4130
4131 // Always consume from window1 since it's the window that has the InputReceiver
4132 consumeMotionEvent(mWindow1, action, expectedPoints);
4133 }
chaviwaf87b3e2019-10-01 16:59:28 -07004134};
4135
4136TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
4137 // Touch Window 1
4138 PointF touchedPoint = {10, 10};
4139 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004140 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004141
4142 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07004143 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004144
4145 // Touch Window 2
4146 touchedPoint = {150, 150};
4147 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004148 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004149}
4150
chaviw9eaa22c2020-07-01 16:21:27 -07004151TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
4152 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07004153 mWindow2->setWindowScale(0.5f, 0.5f);
4154
4155 // Touch Window 1
4156 PointF touchedPoint = {10, 10};
4157 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004158 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004159 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07004160 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004161
4162 // Touch Window 2
4163 touchedPoint = {150, 150};
4164 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004165 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
4166 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004167
chaviw9eaa22c2020-07-01 16:21:27 -07004168 // Update the transform so rotation is set
4169 mWindow2->setWindowTransform(0, -1, 1, 0);
4170 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
4171 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004172}
4173
chaviw9eaa22c2020-07-01 16:21:27 -07004174TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004175 mWindow2->setWindowScale(0.5f, 0.5f);
4176
4177 // Touch Window 1
4178 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4179 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004180 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004181
4182 // Touch Window 2
4183 int32_t actionPointerDown =
4184 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07004185 touchedPoints.push_back(PointF{150, 150});
4186 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
4187 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004188
chaviw9eaa22c2020-07-01 16:21:27 -07004189 // Release Window 2
4190 int32_t actionPointerUp =
4191 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4192 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
4193 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004194
chaviw9eaa22c2020-07-01 16:21:27 -07004195 // Update the transform so rotation is set for Window 2
4196 mWindow2->setWindowTransform(0, -1, 1, 0);
4197 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
4198 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004199}
4200
chaviw9eaa22c2020-07-01 16:21:27 -07004201TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004202 mWindow2->setWindowScale(0.5f, 0.5f);
4203
4204 // Touch Window 1
4205 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4206 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004207 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004208
4209 // Touch Window 2
4210 int32_t actionPointerDown =
4211 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07004212 touchedPoints.push_back(PointF{150, 150});
4213 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004214
chaviw9eaa22c2020-07-01 16:21:27 -07004215 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004216
4217 // Move both windows
4218 touchedPoints = {{20, 20}, {175, 175}};
4219 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4220 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4221
chaviw9eaa22c2020-07-01 16:21:27 -07004222 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004223
chaviw9eaa22c2020-07-01 16:21:27 -07004224 // Release Window 2
4225 int32_t actionPointerUp =
4226 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4227 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
4228 expectedPoints.pop_back();
4229
4230 // Touch Window 2
4231 mWindow2->setWindowTransform(0, -1, 1, 0);
4232 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
4233 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
4234
4235 // Move both windows
4236 touchedPoints = {{20, 20}, {175, 175}};
4237 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4238 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4239
4240 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004241}
4242
4243TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
4244 mWindow1->setWindowScale(0.5f, 0.5f);
4245
4246 // Touch Window 1
4247 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4248 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004249 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004250
4251 // Touch Window 2
4252 int32_t actionPointerDown =
4253 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07004254 touchedPoints.push_back(PointF{150, 150});
4255 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004256
chaviw9eaa22c2020-07-01 16:21:27 -07004257 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004258
4259 // Move both windows
4260 touchedPoints = {{20, 20}, {175, 175}};
4261 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4262 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4263
chaviw9eaa22c2020-07-01 16:21:27 -07004264 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004265}
4266
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004267class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
4268 virtual void SetUp() override {
4269 InputDispatcherTest::SetUp();
4270
Chris Yea209fde2020-07-22 13:54:51 -07004271 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004272 mApplication->setDispatchingTimeout(20ms);
4273 mWindow =
4274 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4275 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004276 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07004277 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004278
4279 // Set focused application.
4280 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
4281
4282 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004283 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004284 mWindow->consumeFocusEvent(true);
4285 }
4286
4287 virtual void TearDown() override {
4288 InputDispatcherTest::TearDown();
4289 mWindow.clear();
4290 }
4291
4292protected:
Chris Yea209fde2020-07-22 13:54:51 -07004293 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004294 sp<FakeWindowHandle> mWindow;
4295 static constexpr PointF WINDOW_LOCATION = {20, 20};
4296
4297 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004299 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4300 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004302 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4303 WINDOW_LOCATION));
4304 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004305
4306 sp<FakeWindowHandle> addSpyWindow() {
4307 sp<FakeWindowHandle> spy =
4308 new FakeWindowHandle(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4309 spy->setTrustedOverlay(true);
4310 spy->setFocusable(false);
4311 spy->setInputFeatures(WindowInfo::Feature::SPY);
4312 spy->setDispatchingTimeout(30ms);
4313 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
4314 return spy;
4315 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004316};
4317
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004318// Send a tap and respond, which should not cause an ANR.
4319TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
4320 tapOnWindow();
4321 mWindow->consumeMotionDown();
4322 mWindow->consumeMotionUp();
4323 ASSERT_TRUE(mDispatcher->waitForIdle());
4324 mFakePolicy->assertNotifyAnrWasNotCalled();
4325}
4326
4327// Send a regular key and respond, which should not cause an ANR.
4328TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004330 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4331 ASSERT_TRUE(mDispatcher->waitForIdle());
4332 mFakePolicy->assertNotifyAnrWasNotCalled();
4333}
4334
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004335TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
4336 mWindow->setFocusable(false);
4337 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4338 mWindow->consumeFocusEvent(false);
4339
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004340 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004341 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004342 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4343 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004345 // Key will not go to window because we have no focused window.
4346 // The 'no focused window' ANR timer should start instead.
4347
4348 // Now, the focused application goes away.
4349 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
4350 // The key should get dropped and there should be no ANR.
4351
4352 ASSERT_TRUE(mDispatcher->waitForIdle());
4353 mFakePolicy->assertNotifyAnrWasNotCalled();
4354}
4355
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004356// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004357// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
4358// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004359TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004361 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4362 WINDOW_LOCATION));
4363
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004364 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
4365 ASSERT_TRUE(sequenceNum);
4366 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004367 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004368
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004369 mWindow->finishEvent(*sequenceNum);
4370 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4371 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004372 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004373 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004374}
4375
4376// Send a key to the app and have the app not respond right away.
4377TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
4378 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004380 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
4381 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004382 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004383 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004384 ASSERT_TRUE(mDispatcher->waitForIdle());
4385}
4386
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004387// We have a focused application, but no focused window
4388TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004389 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004390 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4391 mWindow->consumeFocusEvent(false);
4392
4393 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004395 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4396 WINDOW_LOCATION));
4397 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
4398 mDispatcher->waitForIdle();
4399 mFakePolicy->assertNotifyAnrWasNotCalled();
4400
4401 // Once a focused event arrives, we get an ANR for this application
4402 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4403 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004404 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004405 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004406 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004407 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004408 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004409 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004410 ASSERT_TRUE(mDispatcher->waitForIdle());
4411}
4412
4413// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004414// Make sure that we don't notify policy twice about the same ANR.
4415TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004416 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004417 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4418 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004419
4420 // Once a focused event arrives, we get an ANR for this application
4421 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4422 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004423 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004424 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004425 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004426 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004427 const std::chrono::duration appTimeout =
4428 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004429 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004430
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004431 std::this_thread::sleep_for(appTimeout);
4432 // ANR should not be raised again. It is up to policy to do that if it desires.
4433 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004434
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004435 // If we now get a focused window, the ANR should stop, but the policy handles that via
4436 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004437 ASSERT_TRUE(mDispatcher->waitForIdle());
4438}
4439
4440// We have a focused application, but no focused window
4441TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004442 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004443 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4444 mWindow->consumeFocusEvent(false);
4445
4446 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004447 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004448 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004449 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4450 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004451
4452 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004453 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004454
4455 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004456 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004457 ASSERT_TRUE(mDispatcher->waitForIdle());
4458 mWindow->assertNoEvents();
4459}
4460
4461/**
4462 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
4463 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
4464 * If we process 1 of the events, but ANR on the second event with the same timestamp,
4465 * the ANR mechanism should still work.
4466 *
4467 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
4468 * DOWN event, while not responding on the second one.
4469 */
4470TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
4471 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
4472 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4473 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4474 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4475 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004476 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004477
4478 // Now send ACTION_UP, with identical timestamp
4479 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4480 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4481 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4482 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004483 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004484
4485 // We have now sent down and up. Let's consume first event and then ANR on the second.
4486 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4487 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004488 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004489}
4490
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004491// A spy window can receive an ANR
4492TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
4493 sp<FakeWindowHandle> spy = addSpyWindow();
4494
4495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4496 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4497 WINDOW_LOCATION));
4498 mWindow->consumeMotionDown();
4499
4500 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
4501 ASSERT_TRUE(sequenceNum);
4502 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
4503 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy->getToken());
4504
4505 spy->finishEvent(*sequenceNum);
4506 spy->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
4507 0 /*flags*/);
4508 ASSERT_TRUE(mDispatcher->waitForIdle());
4509 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken());
4510}
4511
4512// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004513// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004514TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
4515 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004516
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4518 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004519 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004521
4522 // Stuck on the ACTION_UP
4523 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004524 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004525
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004526 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004527 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004528 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4529 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004530
4531 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4532 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004533 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004534 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004535 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004536}
4537
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004538// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004539// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004540TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
4541 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004542
4543 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004544 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4545 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004546
4547 mWindow->consumeMotionDown();
4548 // Stuck on the ACTION_UP
4549 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004550 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004551
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004552 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004553 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004554 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4555 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004556
4557 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4558 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004559 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004560 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004561 spy->assertNoEvents();
4562}
4563
4564TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
4565 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
4566
4567 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4568
4569 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4570 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4571 WINDOW_LOCATION));
4572
4573 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4574 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
4575 ASSERT_TRUE(consumeSeq);
4576
4577 mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(30ms);
4578
4579 monitor.finishEvent(*consumeSeq);
4580 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4581
4582 ASSERT_TRUE(mDispatcher->waitForIdle());
4583 mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004584}
4585
4586// If a window is unresponsive, then you get anr. if the window later catches up and starts to
4587// process events, you don't get an anr. When the window later becomes unresponsive again, you
4588// get an ANR again.
4589// 1. tap -> block on ACTION_UP -> receive ANR
4590// 2. consume all pending events (= queue becomes healthy again)
4591// 3. tap again -> block on ACTION_UP again -> receive ANR second time
4592TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
4593 tapOnWindow();
4594
4595 mWindow->consumeMotionDown();
4596 // Block on ACTION_UP
4597 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004598 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004599 mWindow->consumeMotionUp(); // Now the connection should be healthy again
4600 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004601 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004602 mWindow->assertNoEvents();
4603
4604 tapOnWindow();
4605 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004606 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004607 mWindow->consumeMotionUp();
4608
4609 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004610 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004611 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004612 mWindow->assertNoEvents();
4613}
4614
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004615// If a connection remains unresponsive for a while, make sure policy is only notified once about
4616// it.
4617TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004619 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4620 WINDOW_LOCATION));
4621
4622 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004623 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004624 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004625 // 'notifyConnectionUnresponsive' should only be called once per connection
4626 mFakePolicy->assertNotifyAnrWasNotCalled();
4627 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004628 mWindow->consumeMotionDown();
4629 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4630 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4631 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004632 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004633 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004634 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004635}
4636
4637/**
4638 * If a window is processing a motion event, and then a key event comes in, the key event should
4639 * not to to the focused window until the motion is processed.
4640 *
4641 * Warning!!!
4642 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4643 * and the injection timeout that we specify when injecting the key.
4644 * We must have the injection timeout (10ms) be smaller than
4645 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4646 *
4647 * If that value changes, this test should also change.
4648 */
4649TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
4650 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4652
4653 tapOnWindow();
4654 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4655 ASSERT_TRUE(downSequenceNum);
4656 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4657 ASSERT_TRUE(upSequenceNum);
4658 // Don't finish the events yet, and send a key
4659 // Injection will "succeed" because we will eventually give up and send the key to the focused
4660 // window even if motions are still being processed. But because the injection timeout is short,
4661 // we will receive INJECTION_TIMED_OUT as the result.
4662
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004663 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004664 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004665 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4666 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004667 // Key will not be sent to the window, yet, because the window is still processing events
4668 // and the key remains pending, waiting for the touch events to be processed
4669 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4670 ASSERT_FALSE(keySequenceNum);
4671
4672 std::this_thread::sleep_for(500ms);
4673 // if we wait long enough though, dispatcher will give up, and still send the key
4674 // to the focused window, even though we have not yet finished the motion event
4675 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4676 mWindow->finishEvent(*downSequenceNum);
4677 mWindow->finishEvent(*upSequenceNum);
4678}
4679
4680/**
4681 * If a window is processing a motion event, and then a key event comes in, the key event should
4682 * not go to the focused window until the motion is processed.
4683 * If then a new motion comes in, then the pending key event should be going to the currently
4684 * focused window right away.
4685 */
4686TEST_F(InputDispatcherSingleWindowAnr,
4687 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
4688 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4689 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4690
4691 tapOnWindow();
4692 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4693 ASSERT_TRUE(downSequenceNum);
4694 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4695 ASSERT_TRUE(upSequenceNum);
4696 // Don't finish the events yet, and send a key
4697 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004699 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004700 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004701 // At this point, key is still pending, and should not be sent to the application yet.
4702 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4703 ASSERT_FALSE(keySequenceNum);
4704
4705 // Now tap down again. It should cause the pending key to go to the focused window right away.
4706 tapOnWindow();
4707 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
4708 // the other events yet. We can finish events in any order.
4709 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
4710 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
4711 mWindow->consumeMotionDown();
4712 mWindow->consumeMotionUp();
4713 mWindow->assertNoEvents();
4714}
4715
4716class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
4717 virtual void SetUp() override {
4718 InputDispatcherTest::SetUp();
4719
Chris Yea209fde2020-07-22 13:54:51 -07004720 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004721 mApplication->setDispatchingTimeout(10ms);
4722 mUnfocusedWindow =
4723 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
4724 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004725 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004726 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004727
4728 mFocusedWindow =
4729 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004730 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004731 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004732
4733 // Set focused application.
4734 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07004735 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004736
4737 // Expect one focus window exist in display.
4738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004739 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004740 mFocusedWindow->consumeFocusEvent(true);
4741 }
4742
4743 virtual void TearDown() override {
4744 InputDispatcherTest::TearDown();
4745
4746 mUnfocusedWindow.clear();
4747 mFocusedWindow.clear();
4748 }
4749
4750protected:
Chris Yea209fde2020-07-22 13:54:51 -07004751 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004752 sp<FakeWindowHandle> mUnfocusedWindow;
4753 sp<FakeWindowHandle> mFocusedWindow;
4754 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
4755 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
4756 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
4757
4758 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
4759
4760 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
4761
4762private:
4763 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004765 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4766 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004768 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4769 location));
4770 }
4771};
4772
4773// If we have 2 windows that are both unresponsive, the one with the shortest timeout
4774// should be ANR'd first.
4775TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004777 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4778 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004779 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004780 mFocusedWindow->consumeMotionDown();
4781 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4782 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4783 // We consumed all events, so no ANR
4784 ASSERT_TRUE(mDispatcher->waitForIdle());
4785 mFakePolicy->assertNotifyAnrWasNotCalled();
4786
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004788 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4789 FOCUSED_WINDOW_LOCATION));
4790 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
4791 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004792
4793 const std::chrono::duration timeout =
4794 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004795 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004796 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
4797 // sequence to make it consistent
4798 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004799 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004800 mFocusedWindow->consumeMotionDown();
4801 // This cancel is generated because the connection was unresponsive
4802 mFocusedWindow->consumeMotionCancel();
4803 mFocusedWindow->assertNoEvents();
4804 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004805 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004806 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004807 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004808}
4809
4810// If we have 2 windows with identical timeouts that are both unresponsive,
4811// it doesn't matter which order they should have ANR.
4812// But we should receive ANR for both.
4813TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
4814 // Set the timeout for unfocused window to match the focused window
4815 mUnfocusedWindow->setDispatchingTimeout(10ms);
4816 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4817
4818 tapOnFocusedWindow();
4819 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004820 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
4821 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004822
4823 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004824 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
4825 mFocusedWindow->getToken() == anrConnectionToken2);
4826 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
4827 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004828
4829 ASSERT_TRUE(mDispatcher->waitForIdle());
4830 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004831
4832 mFocusedWindow->consumeMotionDown();
4833 mFocusedWindow->consumeMotionUp();
4834 mUnfocusedWindow->consumeMotionOutside();
4835
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004836 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
4837 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004838
4839 // Both applications should be marked as responsive, in any order
4840 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
4841 mFocusedWindow->getToken() == responsiveToken2);
4842 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
4843 mUnfocusedWindow->getToken() == responsiveToken2);
4844 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004845}
4846
4847// If a window is already not responding, the second tap on the same window should be ignored.
4848// We should also log an error to account for the dropped event (not tested here).
4849// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
4850TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
4851 tapOnFocusedWindow();
4852 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4853 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4854 // Receive the events, but don't respond
4855 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
4856 ASSERT_TRUE(downEventSequenceNum);
4857 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
4858 ASSERT_TRUE(upEventSequenceNum);
4859 const std::chrono::duration timeout =
4860 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004861 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004862
4863 // Tap once again
4864 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004865 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004866 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4867 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004868 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004869 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4870 FOCUSED_WINDOW_LOCATION));
4871 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
4872 // valid touch target
4873 mUnfocusedWindow->assertNoEvents();
4874
4875 // Consume the first tap
4876 mFocusedWindow->finishEvent(*downEventSequenceNum);
4877 mFocusedWindow->finishEvent(*upEventSequenceNum);
4878 ASSERT_TRUE(mDispatcher->waitForIdle());
4879 // The second tap did not go to the focused window
4880 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004881 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004882 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004883 mFakePolicy->assertNotifyAnrWasNotCalled();
4884}
4885
4886// If you tap outside of all windows, there will not be ANR
4887TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004888 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004889 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4890 LOCATION_OUTSIDE_ALL_WINDOWS));
4891 ASSERT_TRUE(mDispatcher->waitForIdle());
4892 mFakePolicy->assertNotifyAnrWasNotCalled();
4893}
4894
4895// Since the focused window is paused, tapping on it should not produce any events
4896TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
4897 mFocusedWindow->setPaused(true);
4898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4899
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004900 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004901 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4902 FOCUSED_WINDOW_LOCATION));
4903
4904 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
4905 ASSERT_TRUE(mDispatcher->waitForIdle());
4906 // Should not ANR because the window is paused, and touches shouldn't go to it
4907 mFakePolicy->assertNotifyAnrWasNotCalled();
4908
4909 mFocusedWindow->assertNoEvents();
4910 mUnfocusedWindow->assertNoEvents();
4911}
4912
4913/**
4914 * If a window is processing a motion event, and then a key event comes in, the key event should
4915 * not to to the focused window until the motion is processed.
4916 * If a different window becomes focused at this time, the key should go to that window instead.
4917 *
4918 * Warning!!!
4919 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4920 * and the injection timeout that we specify when injecting the key.
4921 * We must have the injection timeout (10ms) be smaller than
4922 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4923 *
4924 * If that value changes, this test should also change.
4925 */
4926TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
4927 // Set a long ANR timeout to prevent it from triggering
4928 mFocusedWindow->setDispatchingTimeout(2s);
4929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
4930
4931 tapOnUnfocusedWindow();
4932 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
4933 ASSERT_TRUE(downSequenceNum);
4934 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
4935 ASSERT_TRUE(upSequenceNum);
4936 // Don't finish the events yet, and send a key
4937 // Injection will succeed because we will eventually give up and send the key to the focused
4938 // window even if motions are still being processed.
4939
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004940 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004941 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004942 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
4943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004944 // Key will not be sent to the window, yet, because the window is still processing events
4945 // and the key remains pending, waiting for the touch events to be processed
4946 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
4947 ASSERT_FALSE(keySequenceNum);
4948
4949 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07004950 mFocusedWindow->setFocusable(false);
4951 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004952 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004953 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004954
4955 // Focus events should precede the key events
4956 mUnfocusedWindow->consumeFocusEvent(true);
4957 mFocusedWindow->consumeFocusEvent(false);
4958
4959 // Finish the tap events, which should unblock dispatcher
4960 mUnfocusedWindow->finishEvent(*downSequenceNum);
4961 mUnfocusedWindow->finishEvent(*upSequenceNum);
4962
4963 // Now that all queues are cleared and no backlog in the connections, the key event
4964 // can finally go to the newly focused "mUnfocusedWindow".
4965 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4966 mFocusedWindow->assertNoEvents();
4967 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004968 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004969}
4970
4971// When the touch stream is split across 2 windows, and one of them does not respond,
4972// then ANR should be raised and the touch should be canceled for the unresponsive window.
4973// The other window should not be affected by that.
4974TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
4975 // Touch Window 1
4976 NotifyMotionArgs motionArgs =
4977 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4978 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
4979 mDispatcher->notifyMotion(&motionArgs);
4980 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4981 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4982
4983 // Touch Window 2
4984 int32_t actionPointerDown =
4985 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4986
4987 motionArgs =
4988 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4989 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
4990 mDispatcher->notifyMotion(&motionArgs);
4991
4992 const std::chrono::duration timeout =
4993 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004994 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004995
4996 mUnfocusedWindow->consumeMotionDown();
4997 mFocusedWindow->consumeMotionDown();
4998 // Focused window may or may not receive ACTION_MOVE
4999 // But it should definitely receive ACTION_CANCEL due to the ANR
5000 InputEvent* event;
5001 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
5002 ASSERT_TRUE(moveOrCancelSequenceNum);
5003 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
5004 ASSERT_NE(nullptr, event);
5005 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
5006 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5007 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
5008 mFocusedWindow->consumeMotionCancel();
5009 } else {
5010 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
5011 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005012 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00005013 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005014
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005015 mUnfocusedWindow->assertNoEvents();
5016 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005017 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005018}
5019
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005020/**
5021 * If we have no focused window, and a key comes in, we start the ANR timer.
5022 * The focused application should add a focused window before the timer runs out to prevent ANR.
5023 *
5024 * If the user touches another application during this time, the key should be dropped.
5025 * Next, if a new focused window comes in, without toggling the focused application,
5026 * then no ANR should occur.
5027 *
5028 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
5029 * but in some cases the policy may not update the focused application.
5030 */
5031TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
5032 std::shared_ptr<FakeApplicationHandle> focusedApplication =
5033 std::make_shared<FakeApplicationHandle>();
5034 focusedApplication->setDispatchingTimeout(60ms);
5035 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
5036 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
5037 mFocusedWindow->setFocusable(false);
5038
5039 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5040 mFocusedWindow->consumeFocusEvent(false);
5041
5042 // Send a key. The ANR timer should start because there is no focused window.
5043 // 'focusedApplication' will get blamed if this timer completes.
5044 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005045 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005046 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005047 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
5048 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005050
5051 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
5052 // then the injected touches won't cause the focused event to get dropped.
5053 // The dispatcher only checks for whether the queue should be pruned upon queueing.
5054 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
5055 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
5056 // For this test, it means that the key would get delivered to the window once it becomes
5057 // focused.
5058 std::this_thread::sleep_for(10ms);
5059
5060 // Touch unfocused window. This should force the pending key to get dropped.
5061 NotifyMotionArgs motionArgs =
5062 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5063 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
5064 mDispatcher->notifyMotion(&motionArgs);
5065
5066 // We do not consume the motion right away, because that would require dispatcher to first
5067 // process (== drop) the key event, and by that time, ANR will be raised.
5068 // Set the focused window first.
5069 mFocusedWindow->setFocusable(true);
5070 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5071 setFocusedWindow(mFocusedWindow);
5072 mFocusedWindow->consumeFocusEvent(true);
5073 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
5074 // to another application. This could be a bug / behaviour in the policy.
5075
5076 mUnfocusedWindow->consumeMotionDown();
5077
5078 ASSERT_TRUE(mDispatcher->waitForIdle());
5079 // Should not ANR because we actually have a focused window. It was just added too slowly.
5080 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
5081}
5082
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005083// These tests ensure we cannot send touch events to a window that's positioned behind a window
5084// that has feature NO_INPUT_CHANNEL.
5085// Layout:
5086// Top (closest to user)
5087// mNoInputWindow (above all windows)
5088// mBottomWindow
5089// Bottom (furthest from user)
5090class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
5091 virtual void SetUp() override {
5092 InputDispatcherTest::SetUp();
5093
5094 mApplication = std::make_shared<FakeApplicationHandle>();
5095 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
5096 "Window without input channel", ADISPLAY_ID_DEFAULT,
5097 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
5098
chaviw3277faf2021-05-19 16:45:23 -05005099 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005100 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
5101 // It's perfectly valid for this window to not have an associated input channel
5102
5103 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
5104 ADISPLAY_ID_DEFAULT);
5105 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
5106
5107 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
5108 }
5109
5110protected:
5111 std::shared_ptr<FakeApplicationHandle> mApplication;
5112 sp<FakeWindowHandle> mNoInputWindow;
5113 sp<FakeWindowHandle> mBottomWindow;
5114};
5115
5116TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
5117 PointF touchedPoint = {10, 10};
5118
5119 NotifyMotionArgs motionArgs =
5120 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5121 ADISPLAY_ID_DEFAULT, {touchedPoint});
5122 mDispatcher->notifyMotion(&motionArgs);
5123
5124 mNoInputWindow->assertNoEvents();
5125 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
5126 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
5127 // and therefore should prevent mBottomWindow from receiving touches
5128 mBottomWindow->assertNoEvents();
5129}
5130
5131/**
5132 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
5133 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
5134 */
5135TEST_F(InputDispatcherMultiWindowOcclusionTests,
5136 NoInputChannelFeature_DropsTouchesWithValidChannel) {
5137 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
5138 "Window with input channel and NO_INPUT_CHANNEL",
5139 ADISPLAY_ID_DEFAULT);
5140
chaviw3277faf2021-05-19 16:45:23 -05005141 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005142 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
5143 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
5144
5145 PointF touchedPoint = {10, 10};
5146
5147 NotifyMotionArgs motionArgs =
5148 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5149 ADISPLAY_ID_DEFAULT, {touchedPoint});
5150 mDispatcher->notifyMotion(&motionArgs);
5151
5152 mNoInputWindow->assertNoEvents();
5153 mBottomWindow->assertNoEvents();
5154}
5155
Vishnu Nair958da932020-08-21 17:12:37 -07005156class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
5157protected:
5158 std::shared_ptr<FakeApplicationHandle> mApp;
5159 sp<FakeWindowHandle> mWindow;
5160 sp<FakeWindowHandle> mMirror;
5161
5162 virtual void SetUp() override {
5163 InputDispatcherTest::SetUp();
5164 mApp = std::make_shared<FakeApplicationHandle>();
5165 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5166 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
5167 mWindow->getToken());
5168 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5169 mWindow->setFocusable(true);
5170 mMirror->setFocusable(true);
5171 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5172 }
5173};
5174
5175TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
5176 // Request focus on a mirrored window
5177 setFocusedWindow(mMirror);
5178
5179 // window gets focused
5180 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5182 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005183 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
5184}
5185
5186// A focused & mirrored window remains focused only if the window and its mirror are both
5187// focusable.
5188TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
5189 setFocusedWindow(mMirror);
5190
5191 // window gets focused
5192 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5194 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005195 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5197 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005198 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5199
5200 mMirror->setFocusable(false);
5201 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5202
5203 // window loses focus since one of the windows associated with the token in not focusable
5204 mWindow->consumeFocusEvent(false);
5205
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005206 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5207 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005208 mWindow->assertNoEvents();
5209}
5210
5211// A focused & mirrored window remains focused until the window and its mirror both become
5212// invisible.
5213TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
5214 setFocusedWindow(mMirror);
5215
5216 // window gets focused
5217 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5219 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005220 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5222 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005223 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5224
5225 mMirror->setVisible(false);
5226 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5227
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5229 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005230 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5232 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005233 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5234
5235 mWindow->setVisible(false);
5236 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5237
5238 // window loses focus only after all windows associated with the token become invisible.
5239 mWindow->consumeFocusEvent(false);
5240
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005241 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5242 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005243 mWindow->assertNoEvents();
5244}
5245
5246// A focused & mirrored window remains focused until both windows are removed.
5247TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
5248 setFocusedWindow(mMirror);
5249
5250 // window gets focused
5251 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5253 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005254 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5256 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005257 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5258
5259 // single window is removed but the window token remains focused
5260 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
5261
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5263 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005264 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5266 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005267 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5268
5269 // Both windows are removed
5270 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5271 mWindow->consumeFocusEvent(false);
5272
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005273 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5274 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005275 mWindow->assertNoEvents();
5276}
5277
5278// Focus request can be pending until one window becomes visible.
5279TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
5280 // Request focus on an invisible mirror.
5281 mWindow->setVisible(false);
5282 mMirror->setVisible(false);
5283 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5284 setFocusedWindow(mMirror);
5285
5286 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07005288 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005289 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005290
5291 mMirror->setVisible(true);
5292 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5293
5294 // window gets focused
5295 mWindow->consumeFocusEvent(true);
5296 // window gets the pending key event
5297 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5298}
Prabir Pradhan99987712020-11-10 18:43:05 -08005299
5300class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
5301protected:
5302 std::shared_ptr<FakeApplicationHandle> mApp;
5303 sp<FakeWindowHandle> mWindow;
5304 sp<FakeWindowHandle> mSecondWindow;
5305
5306 void SetUp() override {
5307 InputDispatcherTest::SetUp();
5308 mApp = std::make_shared<FakeApplicationHandle>();
5309 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5310 mWindow->setFocusable(true);
5311 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5312 mSecondWindow->setFocusable(true);
5313
5314 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5315 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5316
5317 setFocusedWindow(mWindow);
5318 mWindow->consumeFocusEvent(true);
5319 }
5320
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005321 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
5322 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005323 mDispatcher->notifyPointerCaptureChanged(&args);
5324 }
5325
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005326 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
5327 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08005328 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005329 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
5330 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005331 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005332 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08005333 }
5334};
5335
5336TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
5337 // Ensure that capture cannot be obtained for unfocused windows.
5338 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
5339 mFakePolicy->assertSetPointerCaptureNotCalled();
5340 mSecondWindow->assertNoEvents();
5341
5342 // Ensure that capture can be enabled from the focus window.
5343 requestAndVerifyPointerCapture(mWindow, true);
5344
5345 // Ensure that capture cannot be disabled from a window that does not have capture.
5346 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
5347 mFakePolicy->assertSetPointerCaptureNotCalled();
5348
5349 // Ensure that capture can be disabled from the window with capture.
5350 requestAndVerifyPointerCapture(mWindow, false);
5351}
5352
5353TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005354 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005355
5356 setFocusedWindow(mSecondWindow);
5357
5358 // Ensure that the capture disabled event was sent first.
5359 mWindow->consumeCaptureEvent(false);
5360 mWindow->consumeFocusEvent(false);
5361 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005362 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005363
5364 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005365 notifyPointerCaptureChanged({});
5366 notifyPointerCaptureChanged(request);
5367 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08005368 mWindow->assertNoEvents();
5369 mSecondWindow->assertNoEvents();
5370 mFakePolicy->assertSetPointerCaptureNotCalled();
5371}
5372
5373TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005374 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005375
5376 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005377 notifyPointerCaptureChanged({});
5378 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005379
5380 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005381 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005382 mWindow->consumeCaptureEvent(false);
5383 mWindow->assertNoEvents();
5384}
5385
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005386TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
5387 requestAndVerifyPointerCapture(mWindow, true);
5388
5389 // The first window loses focus.
5390 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005391 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005392 mWindow->consumeCaptureEvent(false);
5393
5394 // Request Pointer Capture from the second window before the notification from InputReader
5395 // arrives.
5396 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005397 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005398
5399 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005400 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005401
5402 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005403 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005404
5405 mSecondWindow->consumeFocusEvent(true);
5406 mSecondWindow->consumeCaptureEvent(true);
5407}
5408
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005409TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
5410 // App repeatedly enables and disables capture.
5411 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5412 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5413 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
5414 mFakePolicy->assertSetPointerCaptureCalled(false);
5415 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5416 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5417
5418 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
5419 // first request is now stale, this should do nothing.
5420 notifyPointerCaptureChanged(firstRequest);
5421 mWindow->assertNoEvents();
5422
5423 // InputReader notifies that the second request was enabled.
5424 notifyPointerCaptureChanged(secondRequest);
5425 mWindow->consumeCaptureEvent(true);
5426}
5427
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005428class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
5429protected:
5430 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00005431
5432 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
5433 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
5434
5435 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
5436 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5437
5438 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
5439 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
5440 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5441 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
5442 MAXIMUM_OBSCURING_OPACITY);
5443
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005444 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005445 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005446 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005447
5448 sp<FakeWindowHandle> mTouchWindow;
5449
5450 virtual void SetUp() override {
5451 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005452 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005453 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
5454 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
5455 }
5456
5457 virtual void TearDown() override {
5458 InputDispatcherTest::TearDown();
5459 mTouchWindow.clear();
5460 }
5461
chaviw3277faf2021-05-19 16:45:23 -05005462 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
5463 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005464 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005465 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005466 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005467 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005468 return window;
5469 }
5470
5471 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
5472 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
5473 sp<FakeWindowHandle> window =
5474 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
5475 // Generate an arbitrary PID based on the UID
5476 window->setOwnerInfo(1777 + (uid % 10000), uid);
5477 return window;
5478 }
5479
5480 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
5481 NotifyMotionArgs args =
5482 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5483 ADISPLAY_ID_DEFAULT, points);
5484 mDispatcher->notifyMotion(&args);
5485 }
5486};
5487
5488TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005489 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005490 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005491 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005492
5493 touch();
5494
5495 mTouchWindow->assertNoEvents();
5496}
5497
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005498TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00005499 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
5500 const sp<FakeWindowHandle>& w =
5501 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
5502 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5503
5504 touch();
5505
5506 mTouchWindow->assertNoEvents();
5507}
5508
5509TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005510 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
5511 const sp<FakeWindowHandle>& w =
5512 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5513 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5514
5515 touch();
5516
5517 w->assertNoEvents();
5518}
5519
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005520TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005521 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
5522 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005523
5524 touch();
5525
5526 mTouchWindow->consumeAnyMotionDown();
5527}
5528
5529TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005530 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005531 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005532 w->setFrame(Rect(0, 0, 50, 50));
5533 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005534
5535 touch({PointF{100, 100}});
5536
5537 mTouchWindow->consumeAnyMotionDown();
5538}
5539
5540TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005541 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005542 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005543 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5544
5545 touch();
5546
5547 mTouchWindow->consumeAnyMotionDown();
5548}
5549
5550TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
5551 const sp<FakeWindowHandle>& w =
5552 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5553 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005554
5555 touch();
5556
5557 mTouchWindow->consumeAnyMotionDown();
5558}
5559
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005560TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
5561 const sp<FakeWindowHandle>& w =
5562 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5563 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5564
5565 touch();
5566
5567 w->assertNoEvents();
5568}
5569
5570/**
5571 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
5572 * inside) while letting them pass-through. Note that even though touch passes through the occluding
5573 * window, the occluding window will still receive ACTION_OUTSIDE event.
5574 */
5575TEST_F(InputDispatcherUntrustedTouchesTest,
5576 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
5577 const sp<FakeWindowHandle>& w =
5578 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005579 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005580 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5581
5582 touch();
5583
5584 w->consumeMotionOutside();
5585}
5586
5587TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
5588 const sp<FakeWindowHandle>& w =
5589 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005590 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5592
5593 touch();
5594
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08005595 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005596}
5597
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005598TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005599 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005600 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5601 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005602 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5603
5604 touch();
5605
5606 mTouchWindow->consumeAnyMotionDown();
5607}
5608
5609TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
5610 const sp<FakeWindowHandle>& w =
5611 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5612 MAXIMUM_OBSCURING_OPACITY);
5613 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005614
5615 touch();
5616
5617 mTouchWindow->consumeAnyMotionDown();
5618}
5619
5620TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005621 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005622 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5623 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005624 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5625
5626 touch();
5627
5628 mTouchWindow->assertNoEvents();
5629}
5630
5631TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
5632 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
5633 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005634 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5635 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005636 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005637 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5638 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005639 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5640
5641 touch();
5642
5643 mTouchWindow->assertNoEvents();
5644}
5645
5646TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
5647 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
5648 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005649 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5650 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005651 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005652 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5653 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5655
5656 touch();
5657
5658 mTouchWindow->consumeAnyMotionDown();
5659}
5660
5661TEST_F(InputDispatcherUntrustedTouchesTest,
5662 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
5663 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005664 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5665 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005666 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005667 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5668 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005669 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5670
5671 touch();
5672
5673 mTouchWindow->consumeAnyMotionDown();
5674}
5675
5676TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
5677 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005678 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5679 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005680 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005681 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5682 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005684
5685 touch();
5686
5687 mTouchWindow->assertNoEvents();
5688}
5689
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005690TEST_F(InputDispatcherUntrustedTouchesTest,
5691 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
5692 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005693 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5694 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005695 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005696 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5697 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005698 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5699
5700 touch();
5701
5702 mTouchWindow->assertNoEvents();
5703}
5704
5705TEST_F(InputDispatcherUntrustedTouchesTest,
5706 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
5707 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005708 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5709 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005710 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005711 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5712 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5714
5715 touch();
5716
5717 mTouchWindow->consumeAnyMotionDown();
5718}
5719
5720TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
5721 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005722 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5723 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005724 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5725
5726 touch();
5727
5728 mTouchWindow->consumeAnyMotionDown();
5729}
5730
5731TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
5732 const sp<FakeWindowHandle>& w =
5733 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
5734 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5735
5736 touch();
5737
5738 mTouchWindow->consumeAnyMotionDown();
5739}
5740
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005741TEST_F(InputDispatcherUntrustedTouchesTest,
5742 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
5743 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5744 const sp<FakeWindowHandle>& w =
5745 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
5746 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5747
5748 touch();
5749
5750 mTouchWindow->assertNoEvents();
5751}
5752
5753TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
5754 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5755 const sp<FakeWindowHandle>& w =
5756 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
5757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5758
5759 touch();
5760
5761 mTouchWindow->consumeAnyMotionDown();
5762}
5763
5764TEST_F(InputDispatcherUntrustedTouchesTest,
5765 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
5766 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
5767 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005768 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5769 OPACITY_ABOVE_THRESHOLD);
5770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5771
5772 touch();
5773
5774 mTouchWindow->consumeAnyMotionDown();
5775}
5776
5777TEST_F(InputDispatcherUntrustedTouchesTest,
5778 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
5779 const sp<FakeWindowHandle>& w1 =
5780 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5781 OPACITY_BELOW_THRESHOLD);
5782 const sp<FakeWindowHandle>& w2 =
5783 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5784 OPACITY_BELOW_THRESHOLD);
5785 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5786
5787 touch();
5788
5789 mTouchWindow->assertNoEvents();
5790}
5791
5792/**
5793 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
5794 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
5795 * (which alone would result in allowing touches) does not affect the blocking behavior.
5796 */
5797TEST_F(InputDispatcherUntrustedTouchesTest,
5798 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
5799 const sp<FakeWindowHandle>& wB =
5800 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5801 OPACITY_BELOW_THRESHOLD);
5802 const sp<FakeWindowHandle>& wC =
5803 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5804 OPACITY_BELOW_THRESHOLD);
5805 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5806
5807 touch();
5808
5809 mTouchWindow->assertNoEvents();
5810}
5811
5812/**
5813 * This test is testing that a window from a different UID but with same application token doesn't
5814 * block the touch. Apps can share the application token for close UI collaboration for example.
5815 */
5816TEST_F(InputDispatcherUntrustedTouchesTest,
5817 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
5818 const sp<FakeWindowHandle>& w =
5819 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5820 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005821 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5822
5823 touch();
5824
5825 mTouchWindow->consumeAnyMotionDown();
5826}
5827
arthurhungb89ccb02020-12-30 16:19:01 +08005828class InputDispatcherDragTests : public InputDispatcherTest {
5829protected:
5830 std::shared_ptr<FakeApplicationHandle> mApp;
5831 sp<FakeWindowHandle> mWindow;
5832 sp<FakeWindowHandle> mSecondWindow;
5833 sp<FakeWindowHandle> mDragWindow;
5834
5835 void SetUp() override {
5836 InputDispatcherTest::SetUp();
5837 mApp = std::make_shared<FakeApplicationHandle>();
5838 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5839 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08005840
5841 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5842 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08005843
5844 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5846 }
5847
5848 // Start performing drag, we will create a drag window and transfer touch to it.
5849 void performDrag() {
5850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5851 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5852 {50, 50}))
5853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5854
5855 // Window should receive motion event.
5856 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5857
5858 // The drag window covers the entire display
5859 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5860 mDispatcher->setInputWindows(
5861 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5862
5863 // Transfer touch focus to the drag window
5864 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5865 true /* isDragDrop */);
5866 mWindow->consumeMotionCancel();
5867 mDragWindow->consumeMotionDown();
5868 }
arthurhung6d4bed92021-03-17 11:59:33 +08005869
5870 // Start performing drag, we will create a drag window and transfer touch to it.
5871 void performStylusDrag() {
5872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5873 injectMotionEvent(mDispatcher,
5874 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
5875 AINPUT_SOURCE_STYLUS)
5876 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5877 .pointer(PointerBuilder(0,
5878 AMOTION_EVENT_TOOL_TYPE_STYLUS)
5879 .x(50)
5880 .y(50))
5881 .build()));
5882 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5883
5884 // The drag window covers the entire display
5885 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5886 mDispatcher->setInputWindows(
5887 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5888
5889 // Transfer touch focus to the drag window
5890 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5891 true /* isDragDrop */);
5892 mWindow->consumeMotionCancel();
5893 mDragWindow->consumeMotionDown();
5894 }
arthurhungb89ccb02020-12-30 16:19:01 +08005895};
5896
5897TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
5898 performDrag();
5899
5900 // Move on window.
5901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5902 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5903 ADISPLAY_ID_DEFAULT, {50, 50}))
5904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5905 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5906 mWindow->consumeDragEvent(false, 50, 50);
5907 mSecondWindow->assertNoEvents();
5908
5909 // Move to another window.
5910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5911 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5912 ADISPLAY_ID_DEFAULT, {150, 50}))
5913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5914 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5915 mWindow->consumeDragEvent(true, 150, 50);
5916 mSecondWindow->consumeDragEvent(false, 50, 50);
5917
5918 // Move back to original window.
5919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5920 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5921 ADISPLAY_ID_DEFAULT, {50, 50}))
5922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5923 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5924 mWindow->consumeDragEvent(false, 50, 50);
5925 mSecondWindow->consumeDragEvent(true, -50, 50);
5926
5927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5928 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
5929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5930 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5931 mWindow->assertNoEvents();
5932 mSecondWindow->assertNoEvents();
5933}
5934
arthurhungf452d0b2021-01-06 00:19:52 +08005935TEST_F(InputDispatcherDragTests, DragAndDrop) {
5936 performDrag();
5937
5938 // Move on window.
5939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5940 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5941 ADISPLAY_ID_DEFAULT, {50, 50}))
5942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5943 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5944 mWindow->consumeDragEvent(false, 50, 50);
5945 mSecondWindow->assertNoEvents();
5946
5947 // Move to another window.
5948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5949 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5950 ADISPLAY_ID_DEFAULT, {150, 50}))
5951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5952 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5953 mWindow->consumeDragEvent(true, 150, 50);
5954 mSecondWindow->consumeDragEvent(false, 50, 50);
5955
5956 // drop to another window.
5957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5958 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5959 {150, 50}))
5960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5961 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5962 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5963 mWindow->assertNoEvents();
5964 mSecondWindow->assertNoEvents();
5965}
5966
arthurhung6d4bed92021-03-17 11:59:33 +08005967TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
5968 performStylusDrag();
5969
5970 // Move on window and keep button pressed.
5971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5972 injectMotionEvent(mDispatcher,
5973 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5974 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5975 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5976 .x(50)
5977 .y(50))
5978 .build()))
5979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5980 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5981 mWindow->consumeDragEvent(false, 50, 50);
5982 mSecondWindow->assertNoEvents();
5983
5984 // Move to another window and release button, expect to drop item.
5985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5986 injectMotionEvent(mDispatcher,
5987 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
5988 .buttonState(0)
5989 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
5990 .x(150)
5991 .y(50))
5992 .build()))
5993 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5994 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5995 mWindow->assertNoEvents();
5996 mSecondWindow->assertNoEvents();
5997 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
5998
5999 // nothing to the window.
6000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6001 injectMotionEvent(mDispatcher,
6002 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
6003 .buttonState(0)
6004 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6005 .x(150)
6006 .y(50))
6007 .build()))
6008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6009 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6010 mWindow->assertNoEvents();
6011 mSecondWindow->assertNoEvents();
6012}
6013
Arthur Hung6d0571e2021-04-09 20:18:16 +08006014TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
6015 performDrag();
6016
6017 // Set second window invisible.
6018 mSecondWindow->setVisible(false);
6019 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
6020
6021 // Move on window.
6022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6023 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6024 ADISPLAY_ID_DEFAULT, {50, 50}))
6025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6026 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6027 mWindow->consumeDragEvent(false, 50, 50);
6028 mSecondWindow->assertNoEvents();
6029
6030 // Move to another window.
6031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6032 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6033 ADISPLAY_ID_DEFAULT, {150, 50}))
6034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6035 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6036 mWindow->consumeDragEvent(true, 150, 50);
6037 mSecondWindow->assertNoEvents();
6038
6039 // drop to another window.
6040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6041 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6042 {150, 50}))
6043 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6044 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6045 mFakePolicy->assertDropTargetEquals(nullptr);
6046 mWindow->assertNoEvents();
6047 mSecondWindow->assertNoEvents();
6048}
6049
Vishnu Nair062a8672021-09-03 16:07:44 -07006050class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
6051
6052TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
6053 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6054 sp<FakeWindowHandle> window =
6055 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
6056 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT);
6057 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6058 window->setFocusable(true);
6059 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
6060 setFocusedWindow(window);
6061 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6062
6063 // With the flag set, window should not get any input
6064 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
6065 mDispatcher->notifyKey(&keyArgs);
6066 window->assertNoEvents();
6067
6068 NotifyMotionArgs motionArgs =
6069 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6070 ADISPLAY_ID_DEFAULT);
6071 mDispatcher->notifyMotion(&motionArgs);
6072 window->assertNoEvents();
6073
6074 // With the flag cleared, the window should get input
6075 window->setInputFeatures({});
6076 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
6077
6078 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
6079 mDispatcher->notifyKey(&keyArgs);
6080 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
6081
6082 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6083 ADISPLAY_ID_DEFAULT);
6084 mDispatcher->notifyMotion(&motionArgs);
6085 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6086 window->assertNoEvents();
6087}
6088
6089TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
6090 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
6091 std::make_shared<FakeApplicationHandle>();
6092 sp<FakeWindowHandle> obscuringWindow =
6093 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
6094 ADISPLAY_ID_DEFAULT);
6095 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
6096 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006097 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07006098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6099 sp<FakeWindowHandle> window =
6100 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
6101 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
6102 window->setOwnerInfo(222, 222);
6103 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6104 window->setFocusable(true);
6105 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
6106 setFocusedWindow(window);
6107 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6108
6109 // With the flag set, window should not get any input
6110 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
6111 mDispatcher->notifyKey(&keyArgs);
6112 window->assertNoEvents();
6113
6114 NotifyMotionArgs motionArgs =
6115 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6116 ADISPLAY_ID_DEFAULT);
6117 mDispatcher->notifyMotion(&motionArgs);
6118 window->assertNoEvents();
6119
6120 // With the flag cleared, the window should get input
6121 window->setInputFeatures({});
6122 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
6123
6124 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
6125 mDispatcher->notifyKey(&keyArgs);
6126 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
6127
6128 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6129 ADISPLAY_ID_DEFAULT);
6130 mDispatcher->notifyMotion(&motionArgs);
6131 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6132 window->assertNoEvents();
6133}
6134
6135TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
6136 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
6137 std::make_shared<FakeApplicationHandle>();
6138 sp<FakeWindowHandle> obscuringWindow =
6139 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
6140 ADISPLAY_ID_DEFAULT);
6141 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
6142 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006143 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07006144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6145 sp<FakeWindowHandle> window =
6146 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
6147 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
6148 window->setOwnerInfo(222, 222);
6149 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6150 window->setFocusable(true);
6151 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
6152 setFocusedWindow(window);
6153 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6154
6155 // With the flag set, window should not get any input
6156 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
6157 mDispatcher->notifyKey(&keyArgs);
6158 window->assertNoEvents();
6159
6160 NotifyMotionArgs motionArgs =
6161 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6162 ADISPLAY_ID_DEFAULT);
6163 mDispatcher->notifyMotion(&motionArgs);
6164 window->assertNoEvents();
6165
6166 // When the window is no longer obscured because it went on top, it should get input
6167 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
6168
6169 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
6170 mDispatcher->notifyKey(&keyArgs);
6171 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
6172
6173 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6174 ADISPLAY_ID_DEFAULT);
6175 mDispatcher->notifyMotion(&motionArgs);
6176 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6177 window->assertNoEvents();
6178}
6179
Antonio Kantekf16f2832021-09-28 04:39:20 +00006180class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
6181protected:
6182 std::shared_ptr<FakeApplicationHandle> mApp;
6183 sp<FakeWindowHandle> mWindow;
6184 sp<FakeWindowHandle> mSecondWindow;
6185
6186 void SetUp() override {
6187 InputDispatcherTest::SetUp();
6188
6189 mApp = std::make_shared<FakeApplicationHandle>();
6190 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
6191 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00006192 setFocusedWindow(mWindow);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006193 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
6194 mSecondWindow->setFocusable(true);
6195
6196 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
6197 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
Antonio Kantekf16f2832021-09-28 04:39:20 +00006198 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00006199
6200 // Set initial touch mode to InputDispatcher::kDefaultInTouchMode.
6201 mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, INJECTOR_PID,
6202 INJECTOR_UID, /* hasPermission */ true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006203 }
6204
Antonio Kantekea47acb2021-12-23 12:41:25 -08006205 void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) {
Antonio Kantek26defcf2022-02-08 01:12:27 +00006206 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission));
Antonio Kantekf16f2832021-09-28 04:39:20 +00006207 mWindow->consumeTouchModeEvent(inTouchMode);
6208 mSecondWindow->consumeTouchModeEvent(inTouchMode);
6209 }
6210};
6211
Antonio Kantek26defcf2022-02-08 01:12:27 +00006212TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08006213 const WindowInfo& windowInfo = *mWindow->getInfo();
6214 changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid,
6215 windowInfo.ownerUid, /* hasPermission */ false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006216}
6217
Antonio Kantek26defcf2022-02-08 01:12:27 +00006218TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
6219 const WindowInfo& windowInfo = *mWindow->getInfo();
6220 int32_t ownerPid = windowInfo.ownerPid;
6221 int32_t ownerUid = windowInfo.ownerUid;
6222 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
6223 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
6224 ownerUid, /* hasPermission */ false));
6225 mWindow->assertNoEvents();
6226 mSecondWindow->assertNoEvents();
6227}
6228
6229TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
6230 const WindowInfo& windowInfo = *mWindow->getInfo();
6231 int32_t ownerPid = windowInfo.ownerPid;
6232 int32_t ownerUid = windowInfo.ownerUid;
6233 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
6234 changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, ownerPid, ownerUid,
6235 /* hasPermission */ true);
6236}
6237
Antonio Kantekf16f2832021-09-28 04:39:20 +00006238TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08006239 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00006240 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
6241 windowInfo.ownerPid, windowInfo.ownerUid,
6242 /* hasPermission */ true));
Antonio Kantekf16f2832021-09-28 04:39:20 +00006243 mWindow->assertNoEvents();
6244 mSecondWindow->assertNoEvents();
6245}
6246
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006247class InputDispatcherSpyWindowTest : public InputDispatcherTest {
6248public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006249 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006250 std::shared_ptr<FakeApplicationHandle> application =
6251 std::make_shared<FakeApplicationHandle>();
6252 std::string name = "Fake Spy ";
6253 name += std::to_string(mSpyCount++);
6254 sp<FakeWindowHandle> spy =
6255 new FakeWindowHandle(application, mDispatcher, name.c_str(), ADISPLAY_ID_DEFAULT);
6256 spy->setInputFeatures(WindowInfo::Feature::SPY);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08006257 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006258 return spy;
6259 }
6260
6261 sp<FakeWindowHandle> createForeground() {
6262 std::shared_ptr<FakeApplicationHandle> application =
6263 std::make_shared<FakeApplicationHandle>();
6264 sp<FakeWindowHandle> window =
6265 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006266 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006267 return window;
6268 }
6269
6270private:
6271 int mSpyCount{0};
6272};
6273
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08006274using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006275/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08006276 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
6277 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08006278TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
6279 ScopedSilentDeath _silentDeath;
6280
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006281 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08006282 spy->setTrustedOverlay(false);
6283 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
6284 ".* not a trusted overlay");
6285}
6286
6287/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006288 * Input injection into a display with a spy window but no foreground windows should succeed.
6289 */
6290TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006291 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006292 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
6293
6294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6295 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6296 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6297 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6298}
6299
6300/**
6301 * Verify the order in which different input windows receive events. The touched foreground window
6302 * (if there is one) should always receive the event first. When there are multiple spy windows, the
6303 * spy windows will receive the event according to their Z-order, where the top-most spy window will
6304 * receive events before ones belows it.
6305 *
6306 * Here, we set up a scenario with four windows in the following Z order from the top:
6307 * spy1, spy2, window, spy3.
6308 * We then inject an event and verify that the foreground "window" receives it first, followed by
6309 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
6310 * window.
6311 */
6312TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
6313 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006314 auto spy1 = createSpy();
6315 auto spy2 = createSpy();
6316 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006317 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
6318 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
6319 const size_t numChannels = channels.size();
6320
Michael Wright8e9a8562022-02-09 13:44:29 +00006321 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006322 if (!epollFd.ok()) {
6323 FAIL() << "Failed to create epoll fd";
6324 }
6325
6326 for (size_t i = 0; i < numChannels; i++) {
6327 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
6328 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
6329 FAIL() << "Failed to add fd to epoll";
6330 }
6331 }
6332
6333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6334 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6335 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6336
6337 std::vector<size_t> eventOrder;
6338 std::vector<struct epoll_event> events(numChannels);
6339 for (;;) {
6340 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
6341 (100ms).count());
6342 if (nFds < 0) {
6343 FAIL() << "Failed to call epoll_wait";
6344 }
6345 if (nFds == 0) {
6346 break; // epoll_wait timed out
6347 }
6348 for (int i = 0; i < nFds; i++) {
6349 ASSERT_EQ(EPOLLIN, events[i].events);
6350 eventOrder.push_back(events[i].data.u64);
6351 channels[i]->consumeMotionDown();
6352 }
6353 }
6354
6355 // Verify the order in which the events were received.
6356 EXPECT_EQ(3u, eventOrder.size());
6357 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
6358 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
6359 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
6360}
6361
6362/**
6363 * A spy window using the NOT_TOUCHABLE flag does not receive events.
6364 */
6365TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
6366 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006367 auto spy = createSpy();
6368 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006369 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6370
6371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6372 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6373 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6374 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6375 spy->assertNoEvents();
6376}
6377
6378/**
6379 * A spy window will only receive gestures that originate within its touchable region. Gestures that
6380 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
6381 * to the window.
6382 */
6383TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
6384 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006385 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006386 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
6387 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6388
6389 // Inject an event outside the spy window's touchable region.
6390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6391 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6392 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6393 window->consumeMotionDown();
6394 spy->assertNoEvents();
6395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6396 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6398 window->consumeMotionUp();
6399 spy->assertNoEvents();
6400
6401 // Inject an event inside the spy window's touchable region.
6402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6403 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6404 {5, 10}))
6405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6406 window->consumeMotionDown();
6407 spy->consumeMotionDown();
6408}
6409
6410/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006411 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006412 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006413 */
6414TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
6415 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006416 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006417 auto spy = createSpy();
6418 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006419 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006420 spy->setFrame(Rect{0, 0, 20, 20});
6421 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6422
6423 // Inject an event outside the spy window's frame and touchable region.
6424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006425 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6426 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006427 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6428 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006429 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006430}
6431
6432/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006433 * A spy window can pilfer pointers. When this happens, touch gestures that are currently sent to
6434 * any other windows - including other spy windows - will also be cancelled.
6435 */
6436TEST_F(InputDispatcherSpyWindowTest, PilferPointers) {
6437 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006438 auto spy1 = createSpy();
6439 auto spy2 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006440 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
6441
6442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6443 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6445 window->consumeMotionDown();
6446 spy1->consumeMotionDown();
6447 spy2->consumeMotionDown();
6448
6449 // Pilfer pointers from the second spy window.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006450 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006451 spy2->assertNoEvents();
6452 spy1->consumeMotionCancel();
6453 window->consumeMotionCancel();
6454
6455 // The rest of the gesture should only be sent to the second spy window.
6456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6457 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6458 ADISPLAY_ID_DEFAULT))
6459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6460 spy2->consumeMotionMove();
6461 spy1->assertNoEvents();
6462 window->assertNoEvents();
6463}
6464
6465/**
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006466 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
6467 * in the middle of the gesture.
6468 */
6469TEST_F(InputDispatcherSpyWindowTest, CanPilferAfterWindowIsRemovedMidStream) {
6470 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006471 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006472 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6473
6474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6475 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6477 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6478 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6479
6480 window->releaseChannel();
6481
6482 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
6483
6484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6485 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6486 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6487 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6488}
6489
6490/**
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006491 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
6492 * the spy, but not to any other windows.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006493 */
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006494TEST_F(InputDispatcherSpyWindowTest, ContinuesToReceiveGestureAfterPilfer) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006495 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006496 auto window = createForeground();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006497
6498 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6499
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006500 // First finger down on the window and the spy.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6502 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6503 {100, 200}))
6504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006505 spy->consumeMotionDown();
6506 window->consumeMotionDown();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006507
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006508 // Spy window pilfers the pointers.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006509 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006510 window->consumeMotionCancel();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006511
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006512 // Second finger down on the window and spy, but the window should not receive the pointer down.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006513 const MotionEvent secondFingerDownEvent =
6514 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6515 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6516 AINPUT_SOURCE_TOUCHSCREEN)
6517 .displayId(ADISPLAY_ID_DEFAULT)
6518 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6519 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
6520 .x(100)
6521 .y(200))
6522 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6523 .build();
6524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6525 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6526 InputEventInjectionSync::WAIT_FOR_RESULT))
6527 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6528
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006529 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
6530
6531 // Third finger goes down outside all windows, so injection should fail.
6532 const MotionEvent thirdFingerDownEvent =
6533 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6534 (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6535 AINPUT_SOURCE_TOUCHSCREEN)
6536 .displayId(ADISPLAY_ID_DEFAULT)
6537 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6538 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
6539 .x(100)
6540 .y(200))
6541 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6542 .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
6543 .build();
6544 ASSERT_EQ(InputEventInjectionResult::FAILED,
6545 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
6546 InputEventInjectionSync::WAIT_FOR_RESULT))
6547 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6548
6549 spy->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006550 window->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006551}
6552
6553/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006554 * Even when a spy window spans over multiple foreground windows, the spy should receive all
6555 * pointers that are down within its bounds.
6556 */
6557TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
6558 auto windowLeft = createForeground();
6559 windowLeft->setFrame({0, 0, 100, 200});
6560 auto windowRight = createForeground();
6561 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006562 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006563 spy->setFrame({0, 0, 200, 200});
6564 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
6565
6566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6567 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6568 {50, 50}))
6569 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6570 windowLeft->consumeMotionDown();
6571 spy->consumeMotionDown();
6572
6573 const MotionEvent secondFingerDownEvent =
6574 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6575 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6576 AINPUT_SOURCE_TOUCHSCREEN)
6577 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6578 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6579 .pointer(
6580 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6581 .build();
6582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6583 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6584 InputEventInjectionSync::WAIT_FOR_RESULT))
6585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6586 windowRight->consumeMotionDown();
6587 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
6588}
6589
6590/**
6591 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
6592 * the spy should receive the second pointer with ACTION_DOWN.
6593 */
6594TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
6595 auto window = createForeground();
6596 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006597 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006598 spyRight->setFrame({100, 0, 200, 200});
6599 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
6600
6601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6602 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6603 {50, 50}))
6604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6605 window->consumeMotionDown();
6606 spyRight->assertNoEvents();
6607
6608 const MotionEvent secondFingerDownEvent =
6609 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6610 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6611 AINPUT_SOURCE_TOUCHSCREEN)
6612 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6613 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6614 .pointer(
6615 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6616 .build();
6617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6618 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6619 InputEventInjectionSync::WAIT_FOR_RESULT))
6620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6621 window->consumeMotionPointerDown(1 /*pointerIndex*/);
6622 spyRight->consumeMotionDown();
6623}
6624
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006625/**
6626 * The spy window should not be able to affect whether or not touches are split. Only the foreground
6627 * windows should be allowed to control split touch.
6628 */
6629TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006630 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006631 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006632 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006633 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006634
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006635 auto window = createForeground();
6636 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006637
6638 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6639
6640 // First finger down, no window touched.
6641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6642 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6643 {100, 200}))
6644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6645 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6646 window->assertNoEvents();
6647
6648 // Second finger down on window, the window should receive touch down.
6649 const MotionEvent secondFingerDownEvent =
6650 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6651 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6652 AINPUT_SOURCE_TOUCHSCREEN)
6653 .displayId(ADISPLAY_ID_DEFAULT)
6654 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6655 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
6656 .x(100)
6657 .y(200))
6658 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6659 .build();
6660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6661 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6662 InputEventInjectionSync::WAIT_FOR_RESULT))
6663 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6664
6665 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6666 spy->consumeMotionPointerDown(1 /* pointerIndex */);
6667}
6668
6669/**
6670 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
6671 * do not receive key events.
6672 */
6673TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006674 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006675 spy->setFocusable(false);
6676
6677 auto window = createForeground();
6678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6679 setFocusedWindow(window);
6680 window->consumeFocusEvent(true);
6681
6682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6683 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
6684 window->consumeKeyDown(ADISPLAY_ID_NONE);
6685
6686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
6687 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
6688 window->consumeKeyUp(ADISPLAY_ID_NONE);
6689
6690 spy->assertNoEvents();
6691}
6692
Prabir Pradhand65552b2021-10-07 11:23:50 -07006693class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
6694public:
6695 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
6696 std::shared_ptr<FakeApplicationHandle> overlayApplication =
6697 std::make_shared<FakeApplicationHandle>();
6698 sp<FakeWindowHandle> overlay =
6699 new FakeWindowHandle(overlayApplication, mDispatcher, "Stylus interceptor window",
6700 ADISPLAY_ID_DEFAULT);
6701 overlay->setFocusable(false);
6702 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006703 overlay->setTouchable(false);
Prabir Pradhand65552b2021-10-07 11:23:50 -07006704 overlay->setInputFeatures(WindowInfo::Feature::INTERCEPTS_STYLUS);
6705 overlay->setTrustedOverlay(true);
6706
6707 std::shared_ptr<FakeApplicationHandle> application =
6708 std::make_shared<FakeApplicationHandle>();
6709 sp<FakeWindowHandle> window =
6710 new FakeWindowHandle(application, mDispatcher, "Application window",
6711 ADISPLAY_ID_DEFAULT);
6712 window->setFocusable(true);
6713 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07006714
6715 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
6717 setFocusedWindow(window);
6718 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6719 return {std::move(overlay), std::move(window)};
6720 }
6721
6722 void sendFingerEvent(int32_t action) {
6723 NotifyMotionArgs motionArgs =
6724 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
6725 ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
6726 mDispatcher->notifyMotion(&motionArgs);
6727 }
6728
6729 void sendStylusEvent(int32_t action) {
6730 NotifyMotionArgs motionArgs =
6731 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
6732 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
6733 motionArgs.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
6734 mDispatcher->notifyMotion(&motionArgs);
6735 }
6736};
6737
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08006738using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
6739
6740TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
6741 ScopedSilentDeath _silentDeath;
6742
Prabir Pradhand65552b2021-10-07 11:23:50 -07006743 auto [overlay, window] = setupStylusOverlayScenario();
6744 overlay->setTrustedOverlay(false);
6745 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
6746 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
6747 ".* not a trusted overlay");
6748}
6749
6750TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
6751 auto [overlay, window] = setupStylusOverlayScenario();
6752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
6753
6754 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
6755 overlay->consumeMotionDown();
6756 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
6757 overlay->consumeMotionUp();
6758
6759 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
6760 window->consumeMotionDown();
6761 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
6762 window->consumeMotionUp();
6763
6764 overlay->assertNoEvents();
6765 window->assertNoEvents();
6766}
6767
6768TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
6769 auto [overlay, window] = setupStylusOverlayScenario();
6770 overlay->setInputFeatures(overlay->getInfo()->inputFeatures | WindowInfo::Feature::SPY);
6771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
6772
6773 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
6774 overlay->consumeMotionDown();
6775 window->consumeMotionDown();
6776 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
6777 overlay->consumeMotionUp();
6778 window->consumeMotionUp();
6779
6780 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
6781 window->consumeMotionDown();
6782 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
6783 window->consumeMotionUp();
6784
6785 overlay->assertNoEvents();
6786 window->assertNoEvents();
6787}
6788
Garfield Tane84e6f92019-08-29 17:28:41 -07006789} // namespace android::inputdispatcher