blob: 8b95f2873890546a7f5f0cc938fe42a38cd52d88 [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 Wrightd02c5b62014-02-10 15:10:22 -080024#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100025#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080026#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080027#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100028
Garfield Tan1c7bc862020-01-28 13:24:04 -080029#include <cinttypes>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070030#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080031#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080032#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033
Garfield Tan1c7bc862020-01-28 13:24:04 -080034using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050035using android::gui::FocusRequest;
36using android::gui::TouchOcclusionMode;
37using android::gui::WindowInfo;
38using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080039using android::os::InputEventInjectionResult;
40using android::os::InputEventInjectionSync;
Michael Wright44753b12020-07-08 13:48:11 +010041using namespace android::flag_operators;
Garfield Tan1c7bc862020-01-28 13:24:04 -080042
Garfield Tane84e6f92019-08-29 17:28:41 -070043namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080044
45// An arbitrary time value.
46static const nsecs_t ARBITRARY_TIME = 1234;
47
48// An arbitrary device id.
49static const int32_t DEVICE_ID = 1;
50
Jeff Brownf086ddb2014-02-11 14:28:48 -080051// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000052static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
53static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080054
Michael Wrightd02c5b62014-02-10 15:10:22 -080055// An arbitrary injector pid / uid pair that has permission to inject events.
56static const int32_t INJECTOR_PID = 999;
57static const int32_t INJECTOR_UID = 1001;
58
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000059// An arbitrary pid of the gesture monitor window
60static constexpr int32_t MONITOR_PID = 2001;
61
chaviwd1c23182019-12-20 18:44:56 -080062struct PointF {
63 float x;
64 float y;
65};
Michael Wrightd02c5b62014-02-10 15:10:22 -080066
Gang Wang342c9272020-01-13 13:15:04 -050067/**
68 * Return a DOWN key event with KEYCODE_A.
69 */
70static KeyEvent getTestKeyEvent() {
71 KeyEvent event;
72
Garfield Tanfbe732e2020-01-24 11:26:14 -080073 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
74 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
75 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -050076 return event;
77}
78
Siarhei Vishniakouca205502021-07-16 21:31:58 +000079static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
80 ASSERT_EQ(expectedAction, receivedAction)
81 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
82 << MotionEvent::actionToString(receivedAction);
83}
84
Michael Wrightd02c5b62014-02-10 15:10:22 -080085// --- FakeInputDispatcherPolicy ---
86
87class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
88 InputDispatcherConfiguration mConfig;
89
90protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100091 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -080092
93public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100094 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +080095
Siarhei Vishniakou8935a802019-11-15 16:41:44 -080096 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -070097 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
98 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
99 EXPECT_EQ(event.getDisplayId(), args.displayId);
100
101 const auto& keyEvent = static_cast<const KeyEvent&>(event);
102 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
103 EXPECT_EQ(keyEvent.getAction(), args.action);
104 });
Jackal Guof9696682018-10-05 12:23:23 +0800105 }
106
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700107 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
108 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
109 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
110 EXPECT_EQ(event.getDisplayId(), args.displayId);
111
112 const auto& motionEvent = static_cast<const MotionEvent&>(event);
113 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
114 EXPECT_EQ(motionEvent.getAction(), args.action);
115 EXPECT_EQ(motionEvent.getX(0), point.x);
116 EXPECT_EQ(motionEvent.getY(0), point.y);
117 EXPECT_EQ(motionEvent.getRawX(0), point.x);
118 EXPECT_EQ(motionEvent.getRawY(0), point.y);
119 });
Jackal Guof9696682018-10-05 12:23:23 +0800120 }
121
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700122 void assertFilterInputEventWasNotCalled() {
123 std::scoped_lock lock(mLock);
124 ASSERT_EQ(nullptr, mFilteredEvent);
125 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800126
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800127 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700128 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800129 ASSERT_TRUE(mConfigurationChangedTime)
130 << "Timed out waiting for configuration changed call";
131 ASSERT_EQ(*mConfigurationChangedTime, when);
132 mConfigurationChangedTime = std::nullopt;
133 }
134
135 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700136 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800137 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800138 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800139 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
140 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
141 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
142 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
143 mLastNotifySwitch = std::nullopt;
144 }
145
chaviwfd6d3512019-03-25 13:23:49 -0700146 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700147 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800148 ASSERT_EQ(touchedToken, mOnPointerDownToken);
149 mOnPointerDownToken.clear();
150 }
151
152 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700153 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800154 ASSERT_TRUE(mOnPointerDownToken == nullptr)
155 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700156 }
157
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700158 // This function must be called soon after the expected ANR timer starts,
159 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500160 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700161 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500162 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
163 std::shared_ptr<InputApplicationHandle> application;
164 { // acquire lock
165 std::unique_lock lock(mLock);
166 android::base::ScopedLockAssertion assumeLocked(mLock);
167 ASSERT_NO_FATAL_FAILURE(
168 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
169 } // release lock
170 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700171 }
172
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000173 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
174 const sp<IBinder>& expectedConnectionToken) {
175 sp<IBinder> connectionToken = getUnresponsiveWindowToken(timeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500176 ASSERT_EQ(expectedConnectionToken, connectionToken);
177 }
178
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000179 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) {
180 sp<IBinder> connectionToken = getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500181 ASSERT_EQ(expectedConnectionToken, connectionToken);
182 }
183
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000184 void assertNotifyMonitorUnresponsiveWasCalled(std::chrono::nanoseconds timeout) {
185 int32_t pid = getUnresponsiveMonitorPid(timeout);
186 ASSERT_EQ(MONITOR_PID, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500187 }
188
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000189 void assertNotifyMonitorResponsiveWasCalled() {
190 int32_t pid = getResponsiveMonitorPid();
191 ASSERT_EQ(MONITOR_PID, pid);
192 }
193
194 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500195 std::unique_lock lock(mLock);
196 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000197 return getAnrTokenLockedInterruptible(timeout, mAnrWindowTokens, lock);
198 }
199
200 sp<IBinder> getResponsiveWindowToken() {
201 std::unique_lock lock(mLock);
202 android::base::ScopedLockAssertion assumeLocked(mLock);
203 return getAnrTokenLockedInterruptible(0s, mResponsiveWindowTokens, lock);
204 }
205
206 int32_t getUnresponsiveMonitorPid(std::chrono::nanoseconds timeout) {
207 std::unique_lock lock(mLock);
208 android::base::ScopedLockAssertion assumeLocked(mLock);
209 return getAnrTokenLockedInterruptible(timeout, mAnrMonitorPids, lock);
210 }
211
212 int32_t getResponsiveMonitorPid() {
213 std::unique_lock lock(mLock);
214 android::base::ScopedLockAssertion assumeLocked(mLock);
215 return getAnrTokenLockedInterruptible(0s, mResponsiveMonitorPids, lock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500216 }
217
218 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
219 // for a specific container to become non-empty. When the container is non-empty, return the
220 // first entry from the container and erase it.
221 template <class T>
222 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
223 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700224 // If there is an ANR, Dispatcher won't be idle because there are still events
225 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
226 // before checking if ANR was called.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500227 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
228 // to provide it some time to act. 100ms seems reasonable.
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800229 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
230 const std::chrono::time_point start = std::chrono::steady_clock::now();
231 std::optional<T> token =
232 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
233 if (!token.has_value()) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500234 ADD_FAILURE() << "Did not receive the ANR callback";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000235 return {};
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700236 }
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800237
238 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700239 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
240 // the dispatcher started counting before this function was called
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700241 if (std::chrono::abs(timeout - waited) > 100ms) {
242 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
243 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
244 << "ms, but waited "
245 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
246 << "ms instead";
247 }
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800248 return *token;
249 }
250
251 template <class T>
252 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
253 std::queue<T>& storage,
254 std::unique_lock<std::mutex>& lock,
255 std::condition_variable& condition)
256 REQUIRES(mLock) {
257 condition.wait_for(lock, timeout,
258 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
259 if (storage.empty()) {
260 ADD_FAILURE() << "Did not receive the expected callback";
261 return std::nullopt;
262 }
263 T item = storage.front();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500264 storage.pop();
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800265 return std::make_optional(item);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700266 }
267
268 void assertNotifyAnrWasNotCalled() {
269 std::scoped_lock lock(mLock);
270 ASSERT_TRUE(mAnrApplications.empty());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000271 ASSERT_TRUE(mAnrWindowTokens.empty());
272 ASSERT_TRUE(mAnrMonitorPids.empty());
273 ASSERT_TRUE(mResponsiveWindowTokens.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500274 << "ANR was not called, but please also consume the 'connection is responsive' "
275 "signal";
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000276 ASSERT_TRUE(mResponsiveMonitorPids.empty())
277 << "Monitor ANR was not called, but please also consume the 'monitor is responsive'"
278 " signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700279 }
280
Garfield Tan1c7bc862020-01-28 13:24:04 -0800281 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
282 mConfig.keyRepeatTimeout = timeout;
283 mConfig.keyRepeatDelay = delay;
284 }
285
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000286 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800287 std::unique_lock lock(mLock);
288 base::ScopedLockAssertion assumeLocked(mLock);
289
290 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
291 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000292 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800293 enabled;
294 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000295 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
296 << ") to be called.";
297 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800298 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000299 auto request = *mPointerCaptureRequest;
300 mPointerCaptureRequest.reset();
301 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800302 }
303
304 void assertSetPointerCaptureNotCalled() {
305 std::unique_lock lock(mLock);
306 base::ScopedLockAssertion assumeLocked(mLock);
307
308 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000309 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800310 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000311 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000313 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800314 }
315
arthurhungf452d0b2021-01-06 00:19:52 +0800316 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
317 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800318 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800319 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800320 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800321 }
322
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800323 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
324 std::unique_lock lock(mLock);
325 base::ScopedLockAssertion assumeLocked(mLock);
326 std::optional<sp<IBinder>> receivedToken =
327 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
328 mNotifyInputChannelBroken);
329 ASSERT_TRUE(receivedToken.has_value());
330 ASSERT_EQ(token, *receivedToken);
331 }
332
Michael Wrightd02c5b62014-02-10 15:10:22 -0800333private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700334 std::mutex mLock;
335 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
336 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
337 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
338 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800339
Prabir Pradhan99987712020-11-10 18:43:05 -0800340 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000341
342 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800343
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700344 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700345 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000346 std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock);
347 std::queue<sp<IBinder>> mResponsiveWindowTokens GUARDED_BY(mLock);
348 std::queue<int32_t> mAnrMonitorPids GUARDED_BY(mLock);
349 std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700350 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800351 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
352 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700353
arthurhungf452d0b2021-01-06 00:19:52 +0800354 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800355 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800356
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600357 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700358 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800359 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800360 }
361
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000362 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700363 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000364 mAnrWindowTokens.push(connectionToken);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700365 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500366 }
367
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000368 void notifyMonitorUnresponsive(int32_t pid, const std::string&) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500369 std::scoped_lock lock(mLock);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000370 mAnrMonitorPids.push(pid);
371 mNotifyAnr.notify_all();
372 }
373
374 void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {
375 std::scoped_lock lock(mLock);
376 mResponsiveWindowTokens.push(connectionToken);
377 mNotifyAnr.notify_all();
378 }
379
380 void notifyMonitorResponsive(int32_t pid) override {
381 std::scoped_lock lock(mLock);
382 mResponsiveMonitorPids.push(pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500383 mNotifyAnr.notify_all();
384 }
385
386 void notifyNoFocusedWindowAnr(
387 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
388 std::scoped_lock lock(mLock);
389 mAnrApplications.push(applicationHandle);
390 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800391 }
392
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800393 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
394 std::scoped_lock lock(mLock);
395 mBrokenInputChannels.push(connectionToken);
396 mNotifyInputChannelBroken.notify_all();
397 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800398
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600399 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700400
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600401 void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
Chris Yef59a2f42020-10-16 12:55:26 -0700402 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
403 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
404 const std::vector<float>& values) override {}
405
406 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
407 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000408
Chris Yefb552902021-02-03 17:18:37 -0800409 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
410
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600411 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800412 *outConfig = mConfig;
413 }
414
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600415 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700416 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800417 switch (inputEvent->getType()) {
418 case AINPUT_EVENT_TYPE_KEY: {
419 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800420 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800421 break;
422 }
423
424 case AINPUT_EVENT_TYPE_MOTION: {
425 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800426 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800427 break;
428 }
429 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800430 return true;
431 }
432
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600433 void interceptKeyBeforeQueueing(const KeyEvent*, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800434
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600435 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800436
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600437 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800438 return 0;
439 }
440
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600441 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800442 return false;
443 }
444
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600445 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
446 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700447 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800448 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
449 * essentially a passthrough for notifySwitch.
450 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800451 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800452 }
453
Sean Stoutb4e0a592021-02-23 07:34:53 -0800454 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800455
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800456 bool checkInjectEventsPermissionNonReentrant(int32_t pid, int32_t uid) override {
457 return pid == INJECTOR_PID && uid == INJECTOR_UID;
458 }
Jackal Guof9696682018-10-05 12:23:23 +0800459
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600460 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700461 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700462 mOnPointerDownToken = newToken;
463 }
464
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000465 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800466 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000467 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800468 mPointerCaptureChangedCondition.notify_all();
469 }
470
arthurhungf452d0b2021-01-06 00:19:52 +0800471 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
472 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800473 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800474 mDropTargetWindowToken = token;
475 }
476
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700477 void assertFilterInputEventWasCalledInternal(
478 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700479 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800480 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700481 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800482 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800483 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800484};
485
Michael Wrightd02c5b62014-02-10 15:10:22 -0800486// --- InputDispatcherTest ---
487
488class InputDispatcherTest : public testing::Test {
489protected:
490 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700491 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800492
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000493 void SetUp() override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800494 mFakePolicy = new FakeInputDispatcherPolicy();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700495 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Arthur Hungb92218b2018-08-14 12:00:21 +0800496 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000497 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700498 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800499 }
500
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000501 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700502 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800503 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700504 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800505 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700506
507 /**
508 * Used for debugging when writing the test
509 */
510 void dumpDispatcherState() {
511 std::string dump;
512 mDispatcher->dump(dump);
513 std::stringstream ss(dump);
514 std::string to;
515
516 while (std::getline(ss, to, '\n')) {
517 ALOGE("%s", to.c_str());
518 }
519 }
Vishnu Nair958da932020-08-21 17:12:37 -0700520
chaviw3277faf2021-05-19 16:45:23 -0500521 void setFocusedWindow(const sp<WindowInfoHandle>& window,
522 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700523 FocusRequest request;
524 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000525 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700526 if (focusedWindow) {
527 request.focusedToken = focusedWindow->getToken();
528 }
529 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
530 request.displayId = window->getInfo()->displayId;
531 mDispatcher->setFocusedWindow(request);
532 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800533};
534
Michael Wrightd02c5b62014-02-10 15:10:22 -0800535TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
536 KeyEvent event;
537
538 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800539 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
540 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600541 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
542 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800543 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700544 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800545 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800546 << "Should reject key events with undefined action.";
547
548 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800549 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
550 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600551 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800552 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700553 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800554 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800555 << "Should reject key events with ACTION_MULTIPLE.";
556}
557
558TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
559 MotionEvent event;
560 PointerProperties pointerProperties[MAX_POINTERS + 1];
561 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800562 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563 pointerProperties[i].clear();
564 pointerProperties[i].id = i;
565 pointerCoords[i].clear();
566 }
567
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800568 // Some constants commonly used below
569 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
570 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
571 constexpr int32_t metaState = AMETA_NONE;
572 constexpr MotionClassification classification = MotionClassification::NONE;
573
chaviw9eaa22c2020-07-01 16:21:27 -0700574 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800575 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800576 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700577 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
578 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700579 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
580 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700581 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800582 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700583 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800584 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800585 << "Should reject motion events with undefined action.";
586
587 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800588 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700589 AMOTION_EVENT_ACTION_POINTER_DOWN |
590 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700591 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
592 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700593 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500594 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800595 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700596 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800597 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800598 << "Should reject motion events with pointer down index too large.";
599
Garfield Tanfbe732e2020-01-24 11:26:14 -0800600 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700601 AMOTION_EVENT_ACTION_POINTER_DOWN |
602 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700603 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
604 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700605 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500606 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800607 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700608 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800609 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800610 << "Should reject motion events with pointer down index too small.";
611
612 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800613 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700614 AMOTION_EVENT_ACTION_POINTER_UP |
615 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700616 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
617 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700618 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500619 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800620 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700621 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800622 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623 << "Should reject motion events with pointer up index too large.";
624
Garfield Tanfbe732e2020-01-24 11:26:14 -0800625 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700626 AMOTION_EVENT_ACTION_POINTER_UP |
627 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700628 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
629 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700630 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500631 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800632 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700633 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800634 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800635 << "Should reject motion events with pointer up index too small.";
636
637 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800638 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
639 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700640 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700641 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
642 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700643 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800644 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700645 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800646 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800647 << "Should reject motion events with 0 pointers.";
648
Garfield Tanfbe732e2020-01-24 11:26:14 -0800649 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
650 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700651 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700652 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
653 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700654 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800655 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700656 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800657 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800658 << "Should reject motion events with more than MAX_POINTERS pointers.";
659
660 // Rejects motion events with invalid pointer ids.
661 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800662 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
663 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700664 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700665 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
666 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700667 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800668 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700669 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800670 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800671 << "Should reject motion events with pointer ids less than 0.";
672
673 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800674 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
675 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700676 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700677 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
678 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700679 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800680 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700681 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800682 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800683 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
684
685 // Rejects motion events with duplicate pointer ids.
686 pointerProperties[0].id = 1;
687 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800688 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
689 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700690 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700691 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
692 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700693 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800694 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700695 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800696 InputEventInjectionSync::NONE, 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800697 << "Should reject motion events with duplicate pointer ids.";
698}
699
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800700/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
701
702TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
703 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800704 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800705 mDispatcher->notifyConfigurationChanged(&args);
706 ASSERT_TRUE(mDispatcher->waitForIdle());
707
708 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
709}
710
711TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800712 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
713 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800714 mDispatcher->notifySwitch(&args);
715
716 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
717 args.policyFlags |= POLICY_FLAG_TRUSTED;
718 mFakePolicy->assertNotifySwitchWasCalled(args);
719}
720
Arthur Hungb92218b2018-08-14 12:00:21 +0800721// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700722static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700723// Default input dispatching timeout if there is no focused application or paused window
724// from which to determine an appropriate dispatching timeout.
725static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
726 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
727 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800728
729class FakeApplicationHandle : public InputApplicationHandle {
730public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700731 FakeApplicationHandle() {
732 mInfo.name = "Fake Application";
733 mInfo.token = new BBinder();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500734 mInfo.dispatchingTimeoutMillis =
735 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700736 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800737 virtual ~FakeApplicationHandle() {}
738
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000739 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700740
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500741 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
742 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700743 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800744};
745
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800746class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800747public:
Garfield Tan15601662020-09-22 15:32:38 -0700748 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800749 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700750 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800751 }
752
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800753 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700754 InputEvent* event;
755 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
756 if (!consumeSeq) {
757 return nullptr;
758 }
759 finishEvent(*consumeSeq);
760 return event;
761 }
762
763 /**
764 * Receive an event without acknowledging it.
765 * Return the sequence number that could later be used to send finished signal.
766 */
767 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800768 uint32_t consumeSeq;
769 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800770
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800771 std::chrono::time_point start = std::chrono::steady_clock::now();
772 status_t status = WOULD_BLOCK;
773 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800774 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800775 &event);
776 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
777 if (elapsed > 100ms) {
778 break;
779 }
780 }
781
782 if (status == WOULD_BLOCK) {
783 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700784 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800785 }
786
787 if (status != OK) {
788 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700789 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800790 }
791 if (event == nullptr) {
792 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700793 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800794 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700795 if (outEvent != nullptr) {
796 *outEvent = event;
797 }
798 return consumeSeq;
799 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800800
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700801 /**
802 * To be used together with "receiveEvent" to complete the consumption of an event.
803 */
804 void finishEvent(uint32_t consumeSeq) {
805 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
806 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800807 }
808
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000809 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
810 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
811 ASSERT_EQ(OK, status);
812 }
813
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000814 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
815 std::optional<int32_t> expectedDisplayId,
816 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800817 InputEvent* event = consume();
818
819 ASSERT_NE(nullptr, event) << mName.c_str()
820 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800821 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700822 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800823 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800824
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000825 if (expectedDisplayId.has_value()) {
826 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
827 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800828
Tiger Huang8664f8c2018-10-11 19:14:35 +0800829 switch (expectedEventType) {
830 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800831 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
832 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000833 if (expectedFlags.has_value()) {
834 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
835 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800836 break;
837 }
838 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800839 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000840 assertMotionAction(expectedAction, motionEvent.getAction());
841
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000842 if (expectedFlags.has_value()) {
843 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
844 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800845 break;
846 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100847 case AINPUT_EVENT_TYPE_FOCUS: {
848 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
849 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800850 case AINPUT_EVENT_TYPE_CAPTURE: {
851 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
852 }
Antonio Kantekf16f2832021-09-28 04:39:20 +0000853 case AINPUT_EVENT_TYPE_TOUCH_MODE: {
854 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
855 }
arthurhungb89ccb02020-12-30 16:19:01 +0800856 case AINPUT_EVENT_TYPE_DRAG: {
857 FAIL() << "Use 'consumeDragEvent' for DRAG events";
858 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800859 default: {
860 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
861 }
862 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800863 }
864
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100865 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
866 InputEvent* event = consume();
867 ASSERT_NE(nullptr, event) << mName.c_str()
868 << ": consumer should have returned non-NULL event.";
869 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
870 << "Got " << inputEventTypeToString(event->getType())
871 << " event instead of FOCUS event";
872
873 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
874 << mName.c_str() << ": event displayId should always be NONE.";
875
876 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
877 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100878 }
879
Prabir Pradhan99987712020-11-10 18:43:05 -0800880 void consumeCaptureEvent(bool hasCapture) {
881 const InputEvent* event = consume();
882 ASSERT_NE(nullptr, event) << mName.c_str()
883 << ": consumer should have returned non-NULL event.";
884 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
885 << "Got " << inputEventTypeToString(event->getType())
886 << " event instead of CAPTURE event";
887
888 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
889 << mName.c_str() << ": event displayId should always be NONE.";
890
891 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
892 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
893 }
894
arthurhungb89ccb02020-12-30 16:19:01 +0800895 void consumeDragEvent(bool isExiting, float x, float y) {
896 const InputEvent* event = consume();
897 ASSERT_NE(nullptr, event) << mName.c_str()
898 << ": consumer should have returned non-NULL event.";
899 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
900 << "Got " << inputEventTypeToString(event->getType())
901 << " event instead of DRAG event";
902
903 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
904 << mName.c_str() << ": event displayId should always be NONE.";
905
906 const auto& dragEvent = static_cast<const DragEvent&>(*event);
907 EXPECT_EQ(isExiting, dragEvent.isExiting());
908 EXPECT_EQ(x, dragEvent.getX());
909 EXPECT_EQ(y, dragEvent.getY());
910 }
911
Antonio Kantekf16f2832021-09-28 04:39:20 +0000912 void consumeTouchModeEvent(bool inTouchMode) {
913 const InputEvent* event = consume();
914 ASSERT_NE(nullptr, event) << mName.c_str()
915 << ": consumer should have returned non-NULL event.";
916 ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
917 << "Got " << inputEventTypeToString(event->getType())
918 << " event instead of TOUCH_MODE event";
919
920 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
921 << mName.c_str() << ": event displayId should always be NONE.";
922 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
923 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
924 }
925
chaviwd1c23182019-12-20 18:44:56 -0800926 void assertNoEvents() {
927 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700928 if (event == nullptr) {
929 return;
930 }
931 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
932 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
933 ADD_FAILURE() << "Received key event "
934 << KeyEvent::actionToString(keyEvent.getAction());
935 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
936 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
937 ADD_FAILURE() << "Received motion event "
938 << MotionEvent::actionToString(motionEvent.getAction());
939 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
940 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
941 ADD_FAILURE() << "Received focus event, hasFocus = "
942 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -0800943 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
944 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
945 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
946 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Antonio Kantekf16f2832021-09-28 04:39:20 +0000947 } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
948 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
949 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
950 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700951 }
952 FAIL() << mName.c_str()
953 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800954 }
955
956 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
957
Prabir Pradhan07e05b62021-11-19 03:57:24 -0800958 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
959
chaviwd1c23182019-12-20 18:44:56 -0800960protected:
961 std::unique_ptr<InputConsumer> mConsumer;
962 PreallocatedInputEventFactory mEventFactory;
963
964 std::string mName;
965};
966
chaviw3277faf2021-05-19 16:45:23 -0500967class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -0800968public:
969 static const int32_t WIDTH = 600;
970 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800971
Chris Yea209fde2020-07-22 13:54:51 -0700972 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700973 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500974 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -0800975 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500976 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -0700977 base::Result<std::unique_ptr<InputChannel>> channel =
978 dispatcher->createInputChannel(name);
979 token = (*channel)->getConnectionToken();
980 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800981 }
982
983 inputApplicationHandle->updateInfo();
984 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
985
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500986 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700987 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800988 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500989 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000990 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -0800991 mInfo.frameLeft = 0;
992 mInfo.frameTop = 0;
993 mInfo.frameRight = WIDTH;
994 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -0700995 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800996 mInfo.globalScaleFactor = 1.0;
997 mInfo.touchableRegion.clear();
998 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
chaviwd1c23182019-12-20 18:44:56 -0800999 mInfo.ownerPid = INJECTOR_PID;
1000 mInfo.ownerUid = INJECTOR_UID;
chaviwd1c23182019-12-20 18:44:56 -08001001 mInfo.displayId = displayId;
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001002 setVisible(true);
1003 setFocusable(false);
1004 setDupTouchToWallpaper(false);
1005 setPaused(false);
1006 setTrustedOverlay(false);
chaviwd1c23182019-12-20 18:44:56 -08001007 }
1008
Arthur Hungabbb9d82021-09-01 14:52:30 +00001009 sp<FakeWindowHandle> clone(
1010 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001011 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001012 sp<FakeWindowHandle> handle =
1013 new FakeWindowHandle(inputApplicationHandle, dispatcher, mInfo.name + "(Mirror)",
1014 displayId, mInfo.token);
1015 return handle;
1016 }
1017
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001018 void setTouchable(bool touchable) {
1019 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1020 }
chaviwd1c23182019-12-20 18:44:56 -08001021
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001022 void setFocusable(bool focusable) {
1023 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1024 }
1025
1026 void setVisible(bool visible) {
1027 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1028 }
Vishnu Nair958da932020-08-21 17:12:37 -07001029
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001030 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001031 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001032 }
1033
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001034 void setPaused(bool paused) {
1035 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1036 }
1037
1038 void setTouchModal(bool touchModal) {
1039 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCH_MODAL, !touchModal);
1040 }
1041
1042 void setSplitTouch(bool splitTouch) {
1043 mInfo.setInputConfig(WindowInfo::InputConfig::SPLIT_TOUCH, splitTouch);
1044 }
1045
1046 void setSlippery(bool slippery) {
1047 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1048 }
1049
1050 void setWatchOutsideTouch(bool watchOutside) {
1051 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1052 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001053
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001054 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1055
chaviw3277faf2021-05-19 16:45:23 -05001056 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001057
Bernardo Rufino7393d172021-02-26 13:56:11 +00001058 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1059
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001060 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001061 mInfo.frameLeft = frame.left;
1062 mInfo.frameTop = frame.top;
1063 mInfo.frameRight = frame.right;
1064 mInfo.frameBottom = frame.bottom;
1065 mInfo.touchableRegion.clear();
1066 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001067
1068 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1069 ui::Transform translate;
1070 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1071 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001072 }
1073
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001074 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1075
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001076 void setIsWallpaper(bool isWallpaper) {
1077 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1078 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001079
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001080 void setDupTouchToWallpaper(bool hasWallpaper) {
1081 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1082 }
chaviwd1c23182019-12-20 18:44:56 -08001083
Prabir Pradhand65552b2021-10-07 11:23:50 -07001084 void setInputFeatures(Flags<WindowInfo::Feature> features) { mInfo.inputFeatures = features; }
1085
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001086 void setTrustedOverlay(bool trustedOverlay) {
1087 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1088 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001089
chaviw9eaa22c2020-07-01 16:21:27 -07001090 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1091 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1092 }
1093
1094 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001095
yunho.shinf4a80b82020-11-16 21:13:57 +09001096 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1097
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001098 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1099 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1100 expectedFlags);
1101 }
1102
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001103 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1104 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1105 }
1106
Svet Ganov5d3bc372020-01-26 23:11:07 -08001107 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001108 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001109 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, expectedDisplayId,
1110 expectedFlags);
1111 }
1112
1113 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001114 int32_t expectedFlags = 0) {
Svet Ganov5d3bc372020-01-26 23:11:07 -08001115 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, expectedDisplayId,
1116 expectedFlags);
1117 }
1118
1119 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001120 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001121 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1122 }
1123
1124 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1125 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001126 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1127 expectedFlags);
1128 }
1129
Svet Ganov5d3bc372020-01-26 23:11:07 -08001130 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001131 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1132 int32_t expectedFlags = 0) {
1133 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
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 consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001139 int32_t expectedFlags = 0) {
1140 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1141 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001142 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1143 }
1144
1145 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001146 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001147 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1148 expectedFlags);
1149 }
1150
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001151 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1152 int32_t expectedFlags = 0) {
1153 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1154 expectedFlags);
1155 }
1156
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001157 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1158 int32_t expectedFlags = 0) {
1159 InputEvent* event = consume();
1160 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
1161 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1162 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1163 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1164 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1165 }
1166
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001167 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1168 ASSERT_NE(mInputReceiver, nullptr)
1169 << "Cannot consume events from a window with no receiver";
1170 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1171 }
1172
Prabir Pradhan99987712020-11-10 18:43:05 -08001173 void consumeCaptureEvent(bool hasCapture) {
1174 ASSERT_NE(mInputReceiver, nullptr)
1175 << "Cannot consume events from a window with no receiver";
1176 mInputReceiver->consumeCaptureEvent(hasCapture);
1177 }
1178
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001179 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1180 std::optional<int32_t> expectedDisplayId,
1181 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001182 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1183 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1184 expectedFlags);
1185 }
1186
arthurhungb89ccb02020-12-30 16:19:01 +08001187 void consumeDragEvent(bool isExiting, float x, float y) {
1188 mInputReceiver->consumeDragEvent(isExiting, x, y);
1189 }
1190
Antonio Kantekf16f2832021-09-28 04:39:20 +00001191 void consumeTouchModeEvent(bool inTouchMode) {
1192 ASSERT_NE(mInputReceiver, nullptr)
1193 << "Cannot consume events from a window with no receiver";
1194 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1195 }
1196
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001197 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001198 if (mInputReceiver == nullptr) {
1199 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1200 return std::nullopt;
1201 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001202 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001203 }
1204
1205 void finishEvent(uint32_t sequenceNum) {
1206 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1207 mInputReceiver->finishEvent(sequenceNum);
1208 }
1209
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001210 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1211 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1212 mInputReceiver->sendTimeline(inputEventId, timeline);
1213 }
1214
chaviwaf87b3e2019-10-01 16:59:28 -07001215 InputEvent* consume() {
1216 if (mInputReceiver == nullptr) {
1217 return nullptr;
1218 }
1219 return mInputReceiver->consume();
1220 }
1221
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001222 MotionEvent* consumeMotion() {
1223 InputEvent* event = consume();
1224 if (event == nullptr) {
1225 ADD_FAILURE() << "Consume failed : no event";
1226 return nullptr;
1227 }
1228 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1229 ADD_FAILURE() << "Instead of motion event, got "
1230 << inputEventTypeToString(event->getType());
1231 return nullptr;
1232 }
1233 return static_cast<MotionEvent*>(event);
1234 }
1235
Arthur Hungb92218b2018-08-14 12:00:21 +08001236 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001237 if (mInputReceiver == nullptr &&
chaviw3277faf2021-05-19 16:45:23 -05001238 mInfo.inputFeatures.test(WindowInfo::Feature::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001239 return; // Can't receive events if the window does not have input channel
1240 }
1241 ASSERT_NE(nullptr, mInputReceiver)
1242 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001243 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001244 }
1245
chaviwaf87b3e2019-10-01 16:59:28 -07001246 sp<IBinder> getToken() { return mInfo.token; }
1247
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001248 const std::string& getName() { return mName; }
1249
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001250 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1251 mInfo.ownerPid = ownerPid;
1252 mInfo.ownerUid = ownerUid;
1253 }
1254
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001255 void destroyReceiver() { mInputReceiver = nullptr; }
1256
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001257 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1258
chaviwd1c23182019-12-20 18:44:56 -08001259private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001260 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001261 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001262 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001263};
1264
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001265std::atomic<int32_t> FakeWindowHandle::sId{1};
1266
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001267static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001268 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001269 int32_t displayId = ADISPLAY_ID_NONE,
1270 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001271 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
1272 bool allowKeyRepeat = true) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001273 KeyEvent event;
1274 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1275
1276 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001277 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001278 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1279 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001280
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001281 int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
1282 if (!allowKeyRepeat) {
1283 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1284 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001285 // Inject event until dispatch out.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001286 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001287 injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001288}
1289
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001290static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001291 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001292 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1293}
1294
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001295// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1296// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1297// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001298static InputEventInjectionResult injectKeyDownNoRepeat(
1299 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001300 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1301 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1302 /* allowKeyRepeat */ false);
1303}
1304
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001305static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001306 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001307 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1308}
1309
Garfield Tandf26e862020-07-01 20:18:19 -07001310class PointerBuilder {
1311public:
1312 PointerBuilder(int32_t id, int32_t toolType) {
1313 mProperties.clear();
1314 mProperties.id = id;
1315 mProperties.toolType = toolType;
1316 mCoords.clear();
1317 }
1318
1319 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1320
1321 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1322
1323 PointerBuilder& axis(int32_t axis, float value) {
1324 mCoords.setAxisValue(axis, value);
1325 return *this;
1326 }
1327
1328 PointerProperties buildProperties() const { return mProperties; }
1329
1330 PointerCoords buildCoords() const { return mCoords; }
1331
1332private:
1333 PointerProperties mProperties;
1334 PointerCoords mCoords;
1335};
1336
1337class MotionEventBuilder {
1338public:
1339 MotionEventBuilder(int32_t action, int32_t source) {
1340 mAction = action;
1341 mSource = source;
1342 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1343 }
1344
1345 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1346 mEventTime = eventTime;
1347 return *this;
1348 }
1349
1350 MotionEventBuilder& displayId(int32_t displayId) {
1351 mDisplayId = displayId;
1352 return *this;
1353 }
1354
1355 MotionEventBuilder& actionButton(int32_t actionButton) {
1356 mActionButton = actionButton;
1357 return *this;
1358 }
1359
arthurhung6d4bed92021-03-17 11:59:33 +08001360 MotionEventBuilder& buttonState(int32_t buttonState) {
1361 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001362 return *this;
1363 }
1364
1365 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1366 mRawXCursorPosition = rawXCursorPosition;
1367 return *this;
1368 }
1369
1370 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1371 mRawYCursorPosition = rawYCursorPosition;
1372 return *this;
1373 }
1374
1375 MotionEventBuilder& pointer(PointerBuilder pointer) {
1376 mPointers.push_back(pointer);
1377 return *this;
1378 }
1379
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001380 MotionEventBuilder& addFlag(uint32_t flags) {
1381 mFlags |= flags;
1382 return *this;
1383 }
1384
Garfield Tandf26e862020-07-01 20:18:19 -07001385 MotionEvent build() {
1386 std::vector<PointerProperties> pointerProperties;
1387 std::vector<PointerCoords> pointerCoords;
1388 for (const PointerBuilder& pointer : mPointers) {
1389 pointerProperties.push_back(pointer.buildProperties());
1390 pointerCoords.push_back(pointer.buildCoords());
1391 }
1392
1393 // Set mouse cursor position for the most common cases to avoid boilerplate.
1394 if (mSource == AINPUT_SOURCE_MOUSE &&
1395 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1396 mPointers.size() == 1) {
1397 mRawXCursorPosition = pointerCoords[0].getX();
1398 mRawYCursorPosition = pointerCoords[0].getY();
1399 }
1400
1401 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001402 ui::Transform identityTransform;
Garfield Tandf26e862020-07-01 20:18:19 -07001403 event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001404 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001405 mButtonState, MotionClassification::NONE, identityTransform,
1406 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001407 mRawYCursorPosition, identityTransform, mEventTime, mEventTime,
1408 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001409
1410 return event;
1411 }
1412
1413private:
1414 int32_t mAction;
1415 int32_t mSource;
1416 nsecs_t mEventTime;
1417 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1418 int32_t mActionButton{0};
1419 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001420 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001421 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1422 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1423
1424 std::vector<PointerBuilder> mPointers;
1425};
1426
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001427static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001428 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001429 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001430 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
Garfield Tandf26e862020-07-01 20:18:19 -07001431 return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
1432 injectionTimeout,
1433 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
1434}
1435
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001436static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001437 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001438 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001439 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001440 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1441 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001442 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001443 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001444 MotionEvent event = MotionEventBuilder(action, source)
1445 .displayId(displayId)
1446 .eventTime(eventTime)
1447 .rawXCursorPosition(cursorPosition.x)
1448 .rawYCursorPosition(cursorPosition.y)
1449 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1450 .x(position.x)
1451 .y(position.y))
1452 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001453
1454 // Inject event until dispatch out.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001455 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode);
Arthur Hungb92218b2018-08-14 12:00:21 +08001456}
1457
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001458static InputEventInjectionResult injectMotionDown(
1459 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1460 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001461 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001462}
1463
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001464static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001465 int32_t source, int32_t displayId,
1466 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001467 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001468}
1469
Jackal Guof9696682018-10-05 12:23:23 +08001470static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1471 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1472 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001473 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1474 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1475 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001476
1477 return args;
1478}
1479
chaviwd1c23182019-12-20 18:44:56 -08001480static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1481 const std::vector<PointF>& points) {
1482 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001483 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1484 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1485 }
1486
chaviwd1c23182019-12-20 18:44:56 -08001487 PointerProperties pointerProperties[pointerCount];
1488 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001489
chaviwd1c23182019-12-20 18:44:56 -08001490 for (size_t i = 0; i < pointerCount; i++) {
1491 pointerProperties[i].clear();
1492 pointerProperties[i].id = i;
1493 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001494
chaviwd1c23182019-12-20 18:44:56 -08001495 pointerCoords[i].clear();
1496 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1497 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1498 }
Jackal Guof9696682018-10-05 12:23:23 +08001499
1500 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1501 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001502 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001503 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1504 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001505 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1506 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001507 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1508 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001509
1510 return args;
1511}
1512
chaviwd1c23182019-12-20 18:44:56 -08001513static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1514 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1515}
1516
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001517static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1518 const PointerCaptureRequest& request) {
1519 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001520}
1521
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001522/**
1523 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1524 * broken channel.
1525 */
1526TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1528 sp<FakeWindowHandle> window =
1529 new FakeWindowHandle(application, mDispatcher, "Window that breaks its input channel",
1530 ADISPLAY_ID_DEFAULT);
1531
1532 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1533
1534 // Window closes its channel, but the window remains.
1535 window->destroyReceiver();
1536 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1537}
1538
Arthur Hungb92218b2018-08-14 12:00:21 +08001539TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001541 sp<FakeWindowHandle> window =
1542 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001543
Arthur Hung72d8dc32020-03-28 00:48:39 +00001544 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1546 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1547 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001548
1549 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001550 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001551}
1552
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001553TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1555 sp<FakeWindowHandle> window =
1556 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1557
1558 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1559 // Inject a MotionEvent to an unknown display.
1560 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1561 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1563
1564 // Window should receive motion event.
1565 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1566}
1567
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001568/**
1569 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
1570 * To ensure that window receives only events that were directly inside of it, add
1571 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1572 * when finding touched windows.
1573 * This test serves as a sanity check for the next test, where setInputWindows is
1574 * called twice.
1575 */
1576TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001577 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001578 sp<FakeWindowHandle> window =
1579 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1580 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001581 window->setTouchModal(false);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001582
1583 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001585 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1586 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001587 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001588
1589 // Window should receive motion event.
1590 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1591}
1592
1593/**
1594 * Calling setInputWindows twice, with the same info, should not cause any issues.
1595 * To ensure that window receives only events that were directly inside of it, add
1596 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
1597 * when finding touched windows.
1598 */
1599TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001600 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001601 sp<FakeWindowHandle> window =
1602 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
1603 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001604 window->setTouchModal(false);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001605
1606 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001609 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1610 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001611 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001612
1613 // Window should receive motion event.
1614 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1615}
1616
Arthur Hungb92218b2018-08-14 12:00:21 +08001617// The foreground window should receive the first touch down event.
1618TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001619 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001620 sp<FakeWindowHandle> windowTop =
1621 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
1622 sp<FakeWindowHandle> windowSecond =
1623 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001624
Arthur Hung72d8dc32020-03-28 00:48:39 +00001625 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1627 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001629
1630 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001631 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001632 windowSecond->assertNoEvents();
1633}
1634
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001635/**
1636 * Two windows: A top window, and a wallpaper behind the window.
1637 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1638 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001639 * 1. foregroundWindow <-- dup touch to wallpaper
1640 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001641 */
1642TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1644 sp<FakeWindowHandle> foregroundWindow =
1645 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001646 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001647 sp<FakeWindowHandle> wallpaperWindow =
1648 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001649 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001650 constexpr int expectedWallpaperFlags =
1651 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1652
1653 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1655 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1656 {100, 200}))
1657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1658
1659 // Both foreground window and its wallpaper should receive the touch down
1660 foregroundWindow->consumeMotionDown();
1661 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1662
1663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1664 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1665 ADISPLAY_ID_DEFAULT, {110, 200}))
1666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1667
1668 foregroundWindow->consumeMotionMove();
1669 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1670
1671 // Now the foreground window goes away, but the wallpaper stays
1672 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1673 foregroundWindow->consumeMotionCancel();
1674 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1675 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1676}
1677
1678/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001679 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1680 * with the following differences:
1681 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1682 * clean up the connection.
1683 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1684 * Ensure that there's no crash in the dispatcher.
1685 */
1686TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1688 sp<FakeWindowHandle> foregroundWindow =
1689 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001690 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001691 sp<FakeWindowHandle> wallpaperWindow =
1692 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001693 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001694 constexpr int expectedWallpaperFlags =
1695 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1696
1697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1699 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1700 {100, 200}))
1701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1702
1703 // Both foreground window and its wallpaper should receive the touch down
1704 foregroundWindow->consumeMotionDown();
1705 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1706
1707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1708 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1709 ADISPLAY_ID_DEFAULT, {110, 200}))
1710 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1711
1712 foregroundWindow->consumeMotionMove();
1713 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1714
1715 // Wallpaper closes its channel, but the window remains.
1716 wallpaperWindow->destroyReceiver();
1717 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1718
1719 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1720 // is no longer valid.
1721 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1722 foregroundWindow->consumeMotionCancel();
1723}
1724
1725/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001726 * A single window that receives touch (on top), and a wallpaper window underneath it.
1727 * The top window gets a multitouch gesture.
1728 * Ensure that wallpaper gets the same gesture.
1729 */
1730TEST_F(InputDispatcherTest, WallpaperWindow_ReceivesMultiTouch) {
1731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1732 sp<FakeWindowHandle> window =
1733 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001734 window->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001735
1736 sp<FakeWindowHandle> wallpaperWindow =
1737 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001738 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001739 constexpr int expectedWallpaperFlags =
1740 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1741
1742 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, wallpaperWindow}}});
1743
1744 // Touch down on top window
1745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1746 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1747 {100, 100}))
1748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1749
1750 // Both top window and its wallpaper should receive the touch down
1751 window->consumeMotionDown();
1752 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1753
1754 // Second finger down on the top window
1755 const MotionEvent secondFingerDownEvent =
1756 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1757 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1758 AINPUT_SOURCE_TOUCHSCREEN)
1759 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1760 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1761 .x(100)
1762 .y(100))
1763 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1764 .x(150)
1765 .y(150))
1766 .build();
1767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1768 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1769 InputEventInjectionSync::WAIT_FOR_RESULT))
1770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1771
1772 window->consumeMotionPointerDown(1 /* pointerIndex */);
1773 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1774 expectedWallpaperFlags);
1775 window->assertNoEvents();
1776 wallpaperWindow->assertNoEvents();
1777}
1778
1779/**
1780 * Two windows: a window on the left and window on the right.
1781 * A third window, wallpaper, is behind both windows, and spans both top windows.
1782 * The first touch down goes to the left window. A second pointer touches down on the right window.
1783 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1784 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1785 * ACTION_POINTER_DOWN(1).
1786 */
1787TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1788 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1789 sp<FakeWindowHandle> leftWindow =
1790 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1791 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001792 leftWindow->setTouchModal(false);
1793 leftWindow->setSplitTouch(true);
1794 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001795
1796 sp<FakeWindowHandle> rightWindow =
1797 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1798 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001799 rightWindow->setTouchModal(false);
1800 rightWindow->setSplitTouch(true);
1801 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001802
1803 sp<FakeWindowHandle> wallpaperWindow =
1804 new FakeWindowHandle(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1805 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001806 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001807 constexpr int expectedWallpaperFlags =
1808 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
1809
1810 mDispatcher->setInputWindows(
1811 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1812
1813 // Touch down on left window
1814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1815 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1816 {100, 100}))
1817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1818
1819 // Both foreground window and its wallpaper should receive the touch down
1820 leftWindow->consumeMotionDown();
1821 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1822
1823 // Second finger down on the right window
1824 const MotionEvent secondFingerDownEvent =
1825 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
1826 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
1827 AINPUT_SOURCE_TOUCHSCREEN)
1828 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1829 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1830 .x(100)
1831 .y(100))
1832 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1833 .x(300)
1834 .y(100))
1835 .build();
1836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1837 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1838 InputEventInjectionSync::WAIT_FOR_RESULT))
1839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1840
1841 leftWindow->consumeMotionMove();
1842 // Since the touch is split, right window gets ACTION_DOWN
1843 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1844 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1845 expectedWallpaperFlags);
1846
1847 // Now, leftWindow, which received the first finger, disappears.
1848 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1849 leftWindow->consumeMotionCancel();
1850 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1851 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1852
1853 // The pointer that's still down on the right window moves, and goes to the right window only.
1854 // As far as the dispatcher's concerned though, both pointers are still present.
1855 const MotionEvent secondFingerMoveEvent =
1856 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1857 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1858 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1859 .x(100)
1860 .y(100))
1861 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1862 .x(310)
1863 .y(110))
1864 .build();
1865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1866 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1867 InputEventInjectionSync::WAIT_FOR_RESULT));
1868 rightWindow->consumeMotionMove();
1869
1870 leftWindow->assertNoEvents();
1871 rightWindow->assertNoEvents();
1872 wallpaperWindow->assertNoEvents();
1873}
1874
Garfield Tandf26e862020-07-01 20:18:19 -07001875TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001876 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001877 sp<FakeWindowHandle> windowLeft =
1878 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1879 windowLeft->setFrame(Rect(0, 0, 600, 800));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001880 windowLeft->setTouchModal(false);
Garfield Tandf26e862020-07-01 20:18:19 -07001881 sp<FakeWindowHandle> windowRight =
1882 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1883 windowRight->setFrame(Rect(600, 0, 1200, 800));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001884 windowRight->setTouchModal(false);
Garfield Tandf26e862020-07-01 20:18:19 -07001885
1886 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1887
1888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
1889
1890 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001892 injectMotionEvent(mDispatcher,
1893 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1894 AINPUT_SOURCE_MOUSE)
1895 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1896 .x(900)
1897 .y(400))
1898 .build()));
1899 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1900 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1901 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1902 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1903
1904 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001906 injectMotionEvent(mDispatcher,
1907 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1908 AINPUT_SOURCE_MOUSE)
1909 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1910 .x(300)
1911 .y(400))
1912 .build()));
1913 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1914 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1915 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1916 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1917 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1918 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1919
1920 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001922 injectMotionEvent(mDispatcher,
1923 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1924 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1925 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1926 .x(300)
1927 .y(400))
1928 .build()));
1929 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1930
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001932 injectMotionEvent(mDispatcher,
1933 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
1934 AINPUT_SOURCE_MOUSE)
1935 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
1936 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1937 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1938 .x(300)
1939 .y(400))
1940 .build()));
1941 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
1942 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1943
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001945 injectMotionEvent(mDispatcher,
1946 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1947 AINPUT_SOURCE_MOUSE)
1948 .buttonState(0)
1949 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
1950 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1951 .x(300)
1952 .y(400))
1953 .build()));
1954 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
1955 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1956
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001958 injectMotionEvent(mDispatcher,
1959 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
1960 .buttonState(0)
1961 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1962 .x(300)
1963 .y(400))
1964 .build()));
1965 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1966
1967 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07001969 injectMotionEvent(mDispatcher,
1970 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1971 AINPUT_SOURCE_MOUSE)
1972 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
1973 .x(900)
1974 .y(400))
1975 .build()));
1976 windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
1977 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1978 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
1979 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1980 windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
1981 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
1982}
1983
1984// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
1985// directly in this test.
1986TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07001987 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07001988 sp<FakeWindowHandle> window =
1989 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1990 window->setFrame(Rect(0, 0, 1200, 800));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001991 window->setTouchModal(false);
Garfield Tandf26e862020-07-01 20:18:19 -07001992
1993 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
1994
1995 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
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_HOVER_ENTER,
2000 AINPUT_SOURCE_MOUSE)
2001 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2002 .x(300)
2003 .y(400))
2004 .build()));
2005 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
2006 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
2007
2008 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002010 injectMotionEvent(mDispatcher,
2011 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2012 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2013 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2014 .x(300)
2015 .y(400))
2016 .build()));
2017 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2018
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002020 injectMotionEvent(mDispatcher,
2021 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
2022 AINPUT_SOURCE_MOUSE)
2023 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2024 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2025 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2026 .x(300)
2027 .y(400))
2028 .build()));
2029 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
2030 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
2031
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002033 injectMotionEvent(mDispatcher,
2034 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2035 AINPUT_SOURCE_MOUSE)
2036 .buttonState(0)
2037 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2038 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2039 .x(300)
2040 .y(400))
2041 .build()));
2042 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2043 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
2044
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002046 injectMotionEvent(mDispatcher,
2047 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
2048 .buttonState(0)
2049 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2050 .x(300)
2051 .y(400))
2052 .build()));
2053 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2054
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002056 injectMotionEvent(mDispatcher,
2057 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
2058 AINPUT_SOURCE_MOUSE)
2059 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2060 .x(300)
2061 .y(400))
2062 .build()));
2063 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
2064 ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
2065}
2066
Garfield Tan00f511d2019-06-12 16:55:40 -07002067TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07002068 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07002069
2070 sp<FakeWindowHandle> windowLeft =
2071 new FakeWindowHandle(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2072 windowLeft->setFrame(Rect(0, 0, 600, 800));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002073 windowLeft->setTouchModal(false);
Garfield Tan00f511d2019-06-12 16:55:40 -07002074 sp<FakeWindowHandle> windowRight =
2075 new FakeWindowHandle(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2076 windowRight->setFrame(Rect(600, 0, 1200, 800));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002077 windowRight->setTouchModal(false);
Garfield Tan00f511d2019-06-12 16:55:40 -07002078
2079 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2080
Arthur Hung72d8dc32020-03-28 00:48:39 +00002081 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07002082
2083 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
2084 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07002086 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002087 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002088 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002089 windowRight->assertNoEvents();
2090}
2091
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002092TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002093 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002094 sp<FakeWindowHandle> window =
2095 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07002096 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002097
Arthur Hung72d8dc32020-03-28 00:48:39 +00002098 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002099 setFocusedWindow(window);
2100
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002101 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002102
2103 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2104 mDispatcher->notifyKey(&keyArgs);
2105
2106 // Window should receive key down event.
2107 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2108
2109 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
2110 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002111 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002112 mDispatcher->notifyDeviceReset(&args);
2113 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2114 AKEY_EVENT_FLAG_CANCELED);
2115}
2116
2117TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002119 sp<FakeWindowHandle> window =
2120 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2121
Arthur Hung72d8dc32020-03-28 00:48:39 +00002122 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002123
2124 NotifyMotionArgs motionArgs =
2125 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2126 ADISPLAY_ID_DEFAULT);
2127 mDispatcher->notifyMotion(&motionArgs);
2128
2129 // Window should receive motion down event.
2130 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2131
2132 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
2133 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002134 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002135 mDispatcher->notifyDeviceReset(&args);
2136 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
2137 0 /*expectedFlags*/);
2138}
2139
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002140/**
2141 * Ensure the correct coordinate spaces are used by InputDispatcher.
2142 *
2143 * InputDispatcher works in the display space, so its coordinate system is relative to the display
2144 * panel. Windows get events in the window space, and get raw coordinates in the logical display
2145 * space.
2146 */
2147class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
2148public:
2149 void SetUp() override {
2150 InputDispatcherTest::SetUp();
2151 mDisplayInfos.clear();
2152 mWindowInfos.clear();
2153 }
2154
2155 void addDisplayInfo(int displayId, const ui::Transform& transform) {
2156 gui::DisplayInfo info;
2157 info.displayId = displayId;
2158 info.transform = transform;
2159 mDisplayInfos.push_back(std::move(info));
2160 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2161 }
2162
2163 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
2164 mWindowInfos.push_back(*windowHandle->getInfo());
2165 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2166 }
2167
2168 // Set up a test scenario where the display has a scaled projection and there are two windows
2169 // on the display.
2170 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
2171 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
2172 // respectively.
2173 ui::Transform displayTransform;
2174 displayTransform.set(2, 0, 0, 4);
2175 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
2176
2177 std::shared_ptr<FakeApplicationHandle> application =
2178 std::make_shared<FakeApplicationHandle>();
2179
2180 // Add two windows to the display. Their frames are represented in the display space.
2181 sp<FakeWindowHandle> firstWindow =
2182 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002183 firstWindow->setTouchModal(false);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002184 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
2185 addWindow(firstWindow);
2186
2187 sp<FakeWindowHandle> secondWindow =
2188 new FakeWindowHandle(application, mDispatcher, "Second Window",
2189 ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002190 secondWindow->setTouchModal(false);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002191 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
2192 addWindow(secondWindow);
2193 return {std::move(firstWindow), std::move(secondWindow)};
2194 }
2195
2196private:
2197 std::vector<gui::DisplayInfo> mDisplayInfos;
2198 std::vector<gui::WindowInfo> mWindowInfos;
2199};
2200
2201TEST_F(InputDispatcherDisplayProjectionTest, HitTestsInDisplaySpace) {
2202 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2203 // Send down to the first window. The point is represented in the display space. The point is
2204 // selected so that if the hit test was done with the transform applied to it, then it would
2205 // end up in the incorrect window.
2206 NotifyMotionArgs downMotionArgs =
2207 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2208 ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
2209 mDispatcher->notifyMotion(&downMotionArgs);
2210
2211 firstWindow->consumeMotionDown();
2212 secondWindow->assertNoEvents();
2213}
2214
2215// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
2216// the event should be treated as being in the logical display space.
2217TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
2218 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2219 // Send down to the first window. The point is represented in the logical display space. The
2220 // point is selected so that if the hit test was done in logical display space, then it would
2221 // end up in the incorrect window.
2222 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2223 PointF{75 * 2, 55 * 4});
2224
2225 firstWindow->consumeMotionDown();
2226 secondWindow->assertNoEvents();
2227}
2228
Prabir Pradhandaa2f142021-12-10 09:30:08 +00002229// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
2230// event should be treated as being in the logical display space.
2231TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
2232 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2233
2234 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
2235 ui::Transform injectedEventTransform;
2236 injectedEventTransform.set(matrix);
2237 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
2238 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
2239
2240 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2241 .displayId(ADISPLAY_ID_DEFAULT)
2242 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2243 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2244 .x(untransformedPoint.x)
2245 .y(untransformedPoint.y))
2246 .build();
2247 event.transform(matrix);
2248
2249 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
2250 InputEventInjectionSync::WAIT_FOR_RESULT);
2251
2252 firstWindow->consumeMotionDown();
2253 secondWindow->assertNoEvents();
2254}
2255
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002256TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
2257 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2258
2259 // Send down to the second window.
2260 NotifyMotionArgs downMotionArgs =
2261 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2262 ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
2263 mDispatcher->notifyMotion(&downMotionArgs);
2264
2265 firstWindow->assertNoEvents();
2266 const MotionEvent* event = secondWindow->consumeMotion();
2267 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
2268
2269 // Ensure that the events from the "getRaw" API are in logical display coordinates.
2270 EXPECT_EQ(300, event->getRawX(0));
2271 EXPECT_EQ(880, event->getRawY(0));
2272
2273 // Ensure that the x and y values are in the window's coordinate space.
2274 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
2275 // the logical display space. This will be the origin of the window space.
2276 EXPECT_EQ(100, event->getX(0));
2277 EXPECT_EQ(80, event->getY(0));
2278}
2279
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002280using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
2281 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002282
2283class TransferTouchFixture : public InputDispatcherTest,
2284 public ::testing::WithParamInterface<TransferFunction> {};
2285
2286TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07002287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002288
2289 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002290 sp<FakeWindowHandle> firstWindow =
2291 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2292 sp<FakeWindowHandle> secondWindow =
2293 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002294
2295 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002296 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002297
2298 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002299 NotifyMotionArgs downMotionArgs =
2300 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2301 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002302 mDispatcher->notifyMotion(&downMotionArgs);
2303 // Only the first window should get the down event
2304 firstWindow->consumeMotionDown();
2305 secondWindow->assertNoEvents();
2306
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002307 // Transfer touch to the second window
2308 TransferFunction f = GetParam();
2309 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2310 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002311 // The first window gets cancel and the second gets down
2312 firstWindow->consumeMotionCancel();
2313 secondWindow->consumeMotionDown();
2314
2315 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002316 NotifyMotionArgs upMotionArgs =
2317 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2318 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002319 mDispatcher->notifyMotion(&upMotionArgs);
2320 // The first window gets no events and the second gets up
2321 firstWindow->assertNoEvents();
2322 secondWindow->consumeMotionUp();
2323}
2324
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002325TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002326 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002327
2328 PointF touchPoint = {10, 10};
2329
2330 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002331 sp<FakeWindowHandle> firstWindow =
2332 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2333 sp<FakeWindowHandle> secondWindow =
2334 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002335
2336 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002337 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002338
2339 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002340 NotifyMotionArgs downMotionArgs =
2341 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2342 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002343 mDispatcher->notifyMotion(&downMotionArgs);
2344 // Only the first window should get the down event
2345 firstWindow->consumeMotionDown();
2346 secondWindow->assertNoEvents();
2347
2348 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002349 NotifyMotionArgs pointerDownMotionArgs =
2350 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2351 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2352 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2353 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002354 mDispatcher->notifyMotion(&pointerDownMotionArgs);
2355 // Only the first window should get the pointer down event
2356 firstWindow->consumeMotionPointerDown(1);
2357 secondWindow->assertNoEvents();
2358
2359 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002360 TransferFunction f = GetParam();
2361 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
2362 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002363 // The first window gets cancel and the second gets down and pointer down
2364 firstWindow->consumeMotionCancel();
2365 secondWindow->consumeMotionDown();
2366 secondWindow->consumeMotionPointerDown(1);
2367
2368 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002369 NotifyMotionArgs pointerUpMotionArgs =
2370 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2371 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2372 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2373 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002374 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2375 // The first window gets nothing and the second gets pointer up
2376 firstWindow->assertNoEvents();
2377 secondWindow->consumeMotionPointerUp(1);
2378
2379 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002380 NotifyMotionArgs upMotionArgs =
2381 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2382 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002383 mDispatcher->notifyMotion(&upMotionArgs);
2384 // The first window gets nothing and the second gets up
2385 firstWindow->assertNoEvents();
2386 secondWindow->consumeMotionUp();
2387}
2388
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002389// For the cases of single pointer touch and two pointers non-split touch, the api's
2390// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
2391// for the case where there are multiple pointers split across several windows.
2392INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
2393 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002394 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
2395 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002396 return dispatcher->transferTouch(destChannelToken);
2397 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002398 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
2399 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002400 return dispatcher->transferTouchFocus(from, to,
2401 false /*isDragAndDrop*/);
2402 }));
2403
Svet Ganov5d3bc372020-01-26 23:11:07 -08002404TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07002405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08002406
2407 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002408 sp<FakeWindowHandle> firstWindow =
2409 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002410 firstWindow->setFrame(Rect(0, 0, 600, 400));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002411 firstWindow->setTouchModal(false);
2412 firstWindow->setSplitTouch(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002413
2414 // Create a non touch modal window that supports split touch
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002415 sp<FakeWindowHandle> secondWindow =
2416 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002417 secondWindow->setFrame(Rect(0, 400, 600, 800));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002418 secondWindow->setTouchModal(false);
2419 secondWindow->setSplitTouch(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002420
2421 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00002422 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002423
2424 PointF pointInFirst = {300, 200};
2425 PointF pointInSecond = {300, 600};
2426
2427 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002428 NotifyMotionArgs firstDownMotionArgs =
2429 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2430 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002431 mDispatcher->notifyMotion(&firstDownMotionArgs);
2432 // Only the first window should get the down event
2433 firstWindow->consumeMotionDown();
2434 secondWindow->assertNoEvents();
2435
2436 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002437 NotifyMotionArgs secondDownMotionArgs =
2438 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2439 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2440 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2441 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002442 mDispatcher->notifyMotion(&secondDownMotionArgs);
2443 // The first window gets a move and the second a down
2444 firstWindow->consumeMotionMove();
2445 secondWindow->consumeMotionDown();
2446
2447 // Transfer touch focus to the second window
2448 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
2449 // The first window gets cancel and the new gets pointer down (it already saw down)
2450 firstWindow->consumeMotionCancel();
2451 secondWindow->consumeMotionPointerDown(1);
2452
2453 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002454 NotifyMotionArgs pointerUpMotionArgs =
2455 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2456 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2457 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2458 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08002459 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2460 // The first window gets nothing and the second gets pointer up
2461 firstWindow->assertNoEvents();
2462 secondWindow->consumeMotionPointerUp(1);
2463
2464 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10002465 NotifyMotionArgs upMotionArgs =
2466 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2467 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08002468 mDispatcher->notifyMotion(&upMotionArgs);
2469 // The first window gets nothing and the second gets up
2470 firstWindow->assertNoEvents();
2471 secondWindow->consumeMotionUp();
2472}
2473
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002474// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
2475// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
2476// touch is not supported, so the touch should continue on those windows and the transferred-to
2477// window should get nothing.
2478TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
2479 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2480
2481 // Create a non touch modal window that supports split touch
2482 sp<FakeWindowHandle> firstWindow =
2483 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2484 firstWindow->setFrame(Rect(0, 0, 600, 400));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002485 firstWindow->setTouchModal(false);
2486 firstWindow->setSplitTouch(true);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002487
2488 // Create a non touch modal window that supports split touch
2489 sp<FakeWindowHandle> secondWindow =
2490 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2491 secondWindow->setFrame(Rect(0, 400, 600, 800));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002492 secondWindow->setTouchModal(false);
2493 secondWindow->setSplitTouch(true);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00002494
2495 // Add the windows to the dispatcher
2496 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2497
2498 PointF pointInFirst = {300, 200};
2499 PointF pointInSecond = {300, 600};
2500
2501 // Send down to the first window
2502 NotifyMotionArgs firstDownMotionArgs =
2503 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2504 ADISPLAY_ID_DEFAULT, {pointInFirst});
2505 mDispatcher->notifyMotion(&firstDownMotionArgs);
2506 // Only the first window should get the down event
2507 firstWindow->consumeMotionDown();
2508 secondWindow->assertNoEvents();
2509
2510 // Send down to the second window
2511 NotifyMotionArgs secondDownMotionArgs =
2512 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2513 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2514 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2515 {pointInFirst, pointInSecond});
2516 mDispatcher->notifyMotion(&secondDownMotionArgs);
2517 // The first window gets a move and the second a down
2518 firstWindow->consumeMotionMove();
2519 secondWindow->consumeMotionDown();
2520
2521 // Transfer touch focus to the second window
2522 const bool transferred = mDispatcher->transferTouch(secondWindow->getToken());
2523 // The 'transferTouch' call should not succeed, because there are 2 touched windows
2524 ASSERT_FALSE(transferred);
2525 firstWindow->assertNoEvents();
2526 secondWindow->assertNoEvents();
2527
2528 // The rest of the dispatch should proceed as normal
2529 // Send pointer up to the second window
2530 NotifyMotionArgs pointerUpMotionArgs =
2531 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2532 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2533 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2534 {pointInFirst, pointInSecond});
2535 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2536 // The first window gets MOVE and the second gets pointer up
2537 firstWindow->consumeMotionMove();
2538 secondWindow->consumeMotionUp();
2539
2540 // Send up event to the first window
2541 NotifyMotionArgs upMotionArgs =
2542 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2543 ADISPLAY_ID_DEFAULT);
2544 mDispatcher->notifyMotion(&upMotionArgs);
2545 // The first window gets nothing and the second gets up
2546 firstWindow->consumeMotionUp();
2547 secondWindow->assertNoEvents();
2548}
2549
Arthur Hungabbb9d82021-09-01 14:52:30 +00002550// This case will create two windows and one mirrored window on the default display and mirror
2551// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
2552// the windows info of second display before default display.
2553TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
2554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2555 sp<FakeWindowHandle> firstWindowInPrimary =
2556 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2557 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002558 firstWindowInPrimary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002559 sp<FakeWindowHandle> secondWindowInPrimary =
2560 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2561 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002562 secondWindowInPrimary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002563
2564 sp<FakeWindowHandle> mirrorWindowInPrimary =
2565 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2566 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002567 mirrorWindowInPrimary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002568
2569 sp<FakeWindowHandle> firstWindowInSecondary =
2570 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2571 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002572 firstWindowInSecondary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002573
2574 sp<FakeWindowHandle> secondWindowInSecondary =
2575 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2576 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002577 secondWindowInPrimary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002578
2579 // Update window info, let it find window handle of second display first.
2580 mDispatcher->setInputWindows(
2581 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2582 {ADISPLAY_ID_DEFAULT,
2583 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2584
2585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2586 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2587 {50, 50}))
2588 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2589
2590 // Window should receive motion event.
2591 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2592
2593 // Transfer touch focus
2594 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
2595 secondWindowInPrimary->getToken()));
2596 // The first window gets cancel.
2597 firstWindowInPrimary->consumeMotionCancel();
2598 secondWindowInPrimary->consumeMotionDown();
2599
2600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2601 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2602 ADISPLAY_ID_DEFAULT, {150, 50}))
2603 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2604 firstWindowInPrimary->assertNoEvents();
2605 secondWindowInPrimary->consumeMotionMove();
2606
2607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2608 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2609 {150, 50}))
2610 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2611 firstWindowInPrimary->assertNoEvents();
2612 secondWindowInPrimary->consumeMotionUp();
2613}
2614
2615// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
2616// 'transferTouch' api.
2617TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
2618 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2619 sp<FakeWindowHandle> firstWindowInPrimary =
2620 new FakeWindowHandle(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
2621 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002622 firstWindowInPrimary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002623 sp<FakeWindowHandle> secondWindowInPrimary =
2624 new FakeWindowHandle(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
2625 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002626 secondWindowInPrimary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002627
2628 sp<FakeWindowHandle> mirrorWindowInPrimary =
2629 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
2630 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002631 mirrorWindowInPrimary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002632
2633 sp<FakeWindowHandle> firstWindowInSecondary =
2634 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2635 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002636 firstWindowInSecondary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002637
2638 sp<FakeWindowHandle> secondWindowInSecondary =
2639 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
2640 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002641 secondWindowInPrimary->setTouchModal(false);
Arthur Hungabbb9d82021-09-01 14:52:30 +00002642
2643 // Update window info, let it find window handle of second display first.
2644 mDispatcher->setInputWindows(
2645 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
2646 {ADISPLAY_ID_DEFAULT,
2647 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
2648
2649 // Touch on second display.
2650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2651 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
2652 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2653
2654 // Window should receive motion event.
2655 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2656
2657 // Transfer touch focus
2658 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken()));
2659
2660 // The first window gets cancel.
2661 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
2662 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
2663
2664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2665 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2666 SECOND_DISPLAY_ID, {150, 50}))
2667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2668 firstWindowInPrimary->assertNoEvents();
2669 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
2670
2671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2672 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
2673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2674 firstWindowInPrimary->assertNoEvents();
2675 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
2676}
2677
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002678TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002679 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002680 sp<FakeWindowHandle> window =
2681 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2682
Vishnu Nair47074b82020-08-14 11:54:47 -07002683 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002684 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002685 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002686
2687 window->consumeFocusEvent(true);
2688
2689 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2690 mDispatcher->notifyKey(&keyArgs);
2691
2692 // Window should receive key down event.
2693 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2694}
2695
2696TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07002697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002698 sp<FakeWindowHandle> window =
2699 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2700
Arthur Hung72d8dc32020-03-28 00:48:39 +00002701 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002702
2703 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2704 mDispatcher->notifyKey(&keyArgs);
2705 mDispatcher->waitForIdle();
2706
2707 window->assertNoEvents();
2708}
2709
2710// If a window is touchable, but does not have focus, it should receive motion events, but not keys
2711TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07002712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002713 sp<FakeWindowHandle> window =
2714 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2715
Arthur Hung72d8dc32020-03-28 00:48:39 +00002716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002717
2718 // Send key
2719 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2720 mDispatcher->notifyKey(&keyArgs);
2721 // Send motion
2722 NotifyMotionArgs motionArgs =
2723 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2724 ADISPLAY_ID_DEFAULT);
2725 mDispatcher->notifyMotion(&motionArgs);
2726
2727 // Window should receive only the motion event
2728 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2729 window->assertNoEvents(); // Key event or focus event will not be received
2730}
2731
arthurhungea3f4fc2020-12-21 23:18:53 +08002732TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
2733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2734
2735 // Create first non touch modal window that supports split touch
2736 sp<FakeWindowHandle> firstWindow =
2737 new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
2738 firstWindow->setFrame(Rect(0, 0, 600, 400));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002739 firstWindow->setTouchModal(false);
2740 firstWindow->setSplitTouch(true);
arthurhungea3f4fc2020-12-21 23:18:53 +08002741
2742 // Create second non touch modal window that supports split touch
2743 sp<FakeWindowHandle> secondWindow =
2744 new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
2745 secondWindow->setFrame(Rect(0, 400, 600, 800));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002746 secondWindow->setTouchModal(false);
2747 secondWindow->setSplitTouch(true);
arthurhungea3f4fc2020-12-21 23:18:53 +08002748
2749 // Add the windows to the dispatcher
2750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
2751
2752 PointF pointInFirst = {300, 200};
2753 PointF pointInSecond = {300, 600};
2754
2755 // Send down to the first window
2756 NotifyMotionArgs firstDownMotionArgs =
2757 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2758 ADISPLAY_ID_DEFAULT, {pointInFirst});
2759 mDispatcher->notifyMotion(&firstDownMotionArgs);
2760 // Only the first window should get the down event
2761 firstWindow->consumeMotionDown();
2762 secondWindow->assertNoEvents();
2763
2764 // Send down to the second window
2765 NotifyMotionArgs secondDownMotionArgs =
2766 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
2767 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2768 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2769 {pointInFirst, pointInSecond});
2770 mDispatcher->notifyMotion(&secondDownMotionArgs);
2771 // The first window gets a move and the second a down
2772 firstWindow->consumeMotionMove();
2773 secondWindow->consumeMotionDown();
2774
2775 // Send pointer cancel to the second window
2776 NotifyMotionArgs pointerUpMotionArgs =
2777 generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
2778 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
2779 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2780 {pointInFirst, pointInSecond});
2781 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
2782 mDispatcher->notifyMotion(&pointerUpMotionArgs);
2783 // The first window gets move and the second gets cancel.
2784 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2785 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
2786
2787 // Send up event.
2788 NotifyMotionArgs upMotionArgs =
2789 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2790 ADISPLAY_ID_DEFAULT);
2791 mDispatcher->notifyMotion(&upMotionArgs);
2792 // The first window gets up and the second gets nothing.
2793 firstWindow->consumeMotionUp();
2794 secondWindow->assertNoEvents();
2795}
2796
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00002797TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
2798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2799
2800 sp<FakeWindowHandle> window =
2801 new FakeWindowHandle(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2802 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2803 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
2804 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
2805 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
2806
2807 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
2808 window->assertNoEvents();
2809 mDispatcher->waitForIdle();
2810}
2811
chaviwd1c23182019-12-20 18:44:56 -08002812class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00002813public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07002814 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002815 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07002816 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08002817 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07002818 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00002819 }
2820
chaviwd1c23182019-12-20 18:44:56 -08002821 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
2822
2823 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2824 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
2825 expectedDisplayId, expectedFlags);
2826 }
2827
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07002828 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
2829
2830 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
2831
chaviwd1c23182019-12-20 18:44:56 -08002832 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2833 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
2834 expectedDisplayId, expectedFlags);
2835 }
2836
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002837 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2838 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
2839 expectedDisplayId, expectedFlags);
2840 }
2841
chaviwd1c23182019-12-20 18:44:56 -08002842 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2843 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
2844 expectedDisplayId, expectedFlags);
2845 }
2846
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002847 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
2848 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
2849 expectedDisplayId, expectedFlags);
2850 }
2851
Arthur Hungfbfa5722021-11-16 02:45:54 +00002852 void consumeMotionPointerDown(int32_t pointerIdx) {
2853 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
2854 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
2855 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
2856 0 /*expectedFlags*/);
2857 }
2858
Evan Rosky84f07f02021-04-16 10:42:42 -07002859 MotionEvent* consumeMotion() {
2860 InputEvent* event = mInputReceiver->consume();
2861 if (!event) {
2862 ADD_FAILURE() << "No event was produced";
2863 return nullptr;
2864 }
2865 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
2866 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
2867 return nullptr;
2868 }
2869 return static_cast<MotionEvent*>(event);
2870 }
2871
chaviwd1c23182019-12-20 18:44:56 -08002872 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
2873
2874private:
2875 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00002876};
2877
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002878using InputDispatcherMonitorTest = InputDispatcherTest;
2879
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002880/**
2881 * Two entities that receive touch: A window, and a global monitor.
2882 * The touch goes to the window, and then the window disappears.
2883 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
2884 * for the monitor, as well.
2885 * 1. foregroundWindow
2886 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
2887 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002888TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2890 sp<FakeWindowHandle> window =
2891 new FakeWindowHandle(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2892
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002893 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002894
2895 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2897 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2898 {100, 200}))
2899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2900
2901 // Both the foreground window and the global monitor should receive the touch down
2902 window->consumeMotionDown();
2903 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
2904
2905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2906 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2907 ADISPLAY_ID_DEFAULT, {110, 200}))
2908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2909
2910 window->consumeMotionMove();
2911 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
2912
2913 // Now the foreground window goes away
2914 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2915 window->consumeMotionCancel();
2916 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
2917
2918 // If more events come in, there will be no more foreground window to send them to. This will
2919 // cause a cancel for the monitor, as well.
2920 ASSERT_EQ(InputEventInjectionResult::FAILED,
2921 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2922 ADISPLAY_ID_DEFAULT, {120, 200}))
2923 << "Injection should fail because the window was removed";
2924 window->assertNoEvents();
2925 // Global monitor now gets the cancel
2926 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
2927}
2928
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002929TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07002930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002931 sp<FakeWindowHandle> window =
2932 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002933 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002934
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002935 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002936
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002938 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00002940 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08002941 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002942}
2943
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002944TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
2945 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002946
Chris Yea209fde2020-07-22 13:54:51 -07002947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Michael Wright3a240c42019-12-10 20:53:41 +00002948 sp<FakeWindowHandle> window =
2949 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00002950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00002951
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00002953 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08002955 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002956 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002957
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002958 // Pilfer pointers from the monitor.
2959 // This should not do anything and the window should continue to receive events.
2960 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00002961
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002963 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2964 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002966
2967 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
2968 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00002969}
2970
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002971TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07002972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2973 sp<FakeWindowHandle> window =
2974 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
2975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2976 window->setWindowOffset(20, 40);
2977 window->setWindowTransform(0, 1, -1, 0);
2978
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002979 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07002980
2981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2982 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
2983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2984 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2985 MotionEvent* event = monitor.consumeMotion();
2986 // Even though window has transform, gesture monitor must not.
2987 ASSERT_EQ(ui::Transform(), event->getTransform());
2988}
2989
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002990TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00002991 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002992 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00002993
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002994 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00002995 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08002996 << "Injection should fail if there is a monitor, but no touchable window";
2997 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00002998}
2999
chaviw81e2bb92019-12-18 15:03:51 -08003000TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
chaviw81e2bb92019-12-18 15:03:51 -08003002 sp<FakeWindowHandle> window =
3003 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
3004
Arthur Hung72d8dc32020-03-28 00:48:39 +00003005 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08003006
3007 NotifyMotionArgs motionArgs =
3008 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3009 ADISPLAY_ID_DEFAULT);
3010
3011 mDispatcher->notifyMotion(&motionArgs);
3012 // Window should receive motion down event.
3013 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3014
3015 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08003016 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08003017 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3018 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
3019 motionArgs.pointerCoords[0].getX() - 10);
3020
3021 mDispatcher->notifyMotion(&motionArgs);
3022 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
3023 0 /*expectedFlags*/);
3024}
3025
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003026/**
3027 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
3028 * the device default right away. In the test scenario, we check both the default value,
3029 * and the action of enabling / disabling.
3030 */
3031TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07003032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003033 sp<FakeWindowHandle> window =
3034 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08003035 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003036
3037 // Set focused application.
3038 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003039 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003040
3041 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00003042 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003043 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003044 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3045
3046 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003047 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003048 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003049 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
3050
3051 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003052 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
3053 /* hasPermission */ true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003054 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07003055 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003056 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003057 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003058 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
3059
3060 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003061 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003062 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003063 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
3064
3065 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003066 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
3067 /* hasPermission */ true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003068 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07003069 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003070 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003071 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003072 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3073
3074 window->assertNoEvents();
3075}
3076
Gang Wange9087892020-01-07 12:17:14 -05003077TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Gang Wange9087892020-01-07 12:17:14 -05003079 sp<FakeWindowHandle> window =
3080 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
3081
3082 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003083 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05003084
Arthur Hung72d8dc32020-03-28 00:48:39 +00003085 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003086 setFocusedWindow(window);
3087
Gang Wange9087892020-01-07 12:17:14 -05003088 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3089
3090 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3091 mDispatcher->notifyKey(&keyArgs);
3092
3093 InputEvent* event = window->consume();
3094 ASSERT_NE(event, nullptr);
3095
3096 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3097 ASSERT_NE(verified, nullptr);
3098 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
3099
3100 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
3101 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
3102 ASSERT_EQ(keyArgs.source, verified->source);
3103 ASSERT_EQ(keyArgs.displayId, verified->displayId);
3104
3105 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
3106
3107 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05003108 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003109 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05003110 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
3111 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
3112 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
3113 ASSERT_EQ(0, verifiedKey.repeatCount);
3114}
3115
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003116TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003117 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003118 sp<FakeWindowHandle> window =
3119 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
3120
3121 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3122
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003123 ui::Transform transform;
3124 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3125
3126 gui::DisplayInfo displayInfo;
3127 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
3128 displayInfo.transform = transform;
3129
3130 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003131
3132 NotifyMotionArgs motionArgs =
3133 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3134 ADISPLAY_ID_DEFAULT);
3135 mDispatcher->notifyMotion(&motionArgs);
3136
3137 InputEvent* event = window->consume();
3138 ASSERT_NE(event, nullptr);
3139
3140 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3141 ASSERT_NE(verified, nullptr);
3142 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
3143
3144 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
3145 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
3146 EXPECT_EQ(motionArgs.source, verified->source);
3147 EXPECT_EQ(motionArgs.displayId, verified->displayId);
3148
3149 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
3150
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003151 const vec2 rawXY =
3152 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
3153 motionArgs.pointerCoords[0].getXYValue());
3154 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
3155 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003156 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003157 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003158 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003159 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
3160 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
3161}
3162
chaviw09c8d2d2020-08-24 15:48:26 -07003163/**
3164 * Ensure that separate calls to sign the same data are generating the same key.
3165 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
3166 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
3167 * tests.
3168 */
3169TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
3170 KeyEvent event = getTestKeyEvent();
3171 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
3172
3173 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
3174 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
3175 ASSERT_EQ(hmac1, hmac2);
3176}
3177
3178/**
3179 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
3180 */
3181TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
3182 KeyEvent event = getTestKeyEvent();
3183 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
3184 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
3185
3186 verifiedEvent.deviceId += 1;
3187 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3188
3189 verifiedEvent.source += 1;
3190 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3191
3192 verifiedEvent.eventTimeNanos += 1;
3193 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3194
3195 verifiedEvent.displayId += 1;
3196 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3197
3198 verifiedEvent.action += 1;
3199 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3200
3201 verifiedEvent.downTimeNanos += 1;
3202 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3203
3204 verifiedEvent.flags += 1;
3205 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3206
3207 verifiedEvent.keyCode += 1;
3208 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3209
3210 verifiedEvent.scanCode += 1;
3211 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3212
3213 verifiedEvent.metaState += 1;
3214 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3215
3216 verifiedEvent.repeatCount += 1;
3217 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
3218}
3219
Vishnu Nair958da932020-08-21 17:12:37 -07003220TEST_F(InputDispatcherTest, SetFocusedWindow) {
3221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3222 sp<FakeWindowHandle> windowTop =
3223 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3224 sp<FakeWindowHandle> windowSecond =
3225 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3226 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3227
3228 // Top window is also focusable but is not granted focus.
3229 windowTop->setFocusable(true);
3230 windowSecond->setFocusable(true);
3231 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3232 setFocusedWindow(windowSecond);
3233
3234 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3236 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003237
3238 // Focused window should receive event.
3239 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3240 windowTop->assertNoEvents();
3241}
3242
3243TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
3244 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3245 sp<FakeWindowHandle> window =
3246 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3247 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3248
3249 window->setFocusable(true);
3250 // Release channel for window is no longer valid.
3251 window->releaseChannel();
3252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3253 setFocusedWindow(window);
3254
3255 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003256 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3257 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003258
3259 // window channel is invalid, so it should not receive any input event.
3260 window->assertNoEvents();
3261}
3262
3263TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
3264 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3265 sp<FakeWindowHandle> window =
3266 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3267 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3268
3269 // Window is not focusable.
3270 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3271 setFocusedWindow(window);
3272
3273 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003274 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3275 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003276
3277 // window is invalid, so it should not receive any input event.
3278 window->assertNoEvents();
3279}
3280
3281TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
3282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3283 sp<FakeWindowHandle> windowTop =
3284 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3285 sp<FakeWindowHandle> windowSecond =
3286 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3287 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3288
3289 windowTop->setFocusable(true);
3290 windowSecond->setFocusable(true);
3291 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3292 setFocusedWindow(windowTop);
3293 windowTop->consumeFocusEvent(true);
3294
3295 setFocusedWindow(windowSecond, windowTop);
3296 windowSecond->consumeFocusEvent(true);
3297 windowTop->consumeFocusEvent(false);
3298
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3300 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003301
3302 // Focused window should receive event.
3303 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
3304}
3305
3306TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
3307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3308 sp<FakeWindowHandle> windowTop =
3309 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
3310 sp<FakeWindowHandle> windowSecond =
3311 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3312 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3313
3314 windowTop->setFocusable(true);
3315 windowSecond->setFocusable(true);
3316 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
3317 setFocusedWindow(windowSecond, windowTop);
3318
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003319 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
3320 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07003321
3322 // Event should be dropped.
3323 windowTop->assertNoEvents();
3324 windowSecond->assertNoEvents();
3325}
3326
3327TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
3328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3329 sp<FakeWindowHandle> window =
3330 new FakeWindowHandle(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
3331 sp<FakeWindowHandle> previousFocusedWindow =
3332 new FakeWindowHandle(application, mDispatcher, "previousFocusedWindow",
3333 ADISPLAY_ID_DEFAULT);
3334 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3335
3336 window->setFocusable(true);
3337 previousFocusedWindow->setFocusable(true);
3338 window->setVisible(false);
3339 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
3340 setFocusedWindow(previousFocusedWindow);
3341 previousFocusedWindow->consumeFocusEvent(true);
3342
3343 // Requesting focus on invisible window takes focus from currently focused window.
3344 setFocusedWindow(window);
3345 previousFocusedWindow->consumeFocusEvent(false);
3346
3347 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07003349 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003350 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07003351
3352 // Window does not get focus event or key down.
3353 window->assertNoEvents();
3354
3355 // Window becomes visible.
3356 window->setVisible(true);
3357 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3358
3359 // Window receives focus event.
3360 window->consumeFocusEvent(true);
3361 // Focused window receives key down.
3362 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3363}
3364
Vishnu Nair599f1412021-06-21 10:39:58 -07003365TEST_F(InputDispatcherTest, DisplayRemoved) {
3366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3367 sp<FakeWindowHandle> window =
3368 new FakeWindowHandle(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
3369 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3370
3371 // window is granted focus.
3372 window->setFocusable(true);
3373 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3374 setFocusedWindow(window);
3375 window->consumeFocusEvent(true);
3376
3377 // When a display is removed window loses focus.
3378 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
3379 window->consumeFocusEvent(false);
3380}
3381
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003382/**
3383 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
3384 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
3385 * of the 'slipperyEnterWindow'.
3386 *
3387 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
3388 * a way so that the touched location is no longer covered by the top window.
3389 *
3390 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
3391 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
3392 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
3393 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
3394 * with ACTION_DOWN).
3395 * Thus, the touch has been transferred from the top window into the bottom window, because the top
3396 * window moved itself away from the touched location and had Flag::SLIPPERY.
3397 *
3398 * Even though the top window moved away from the touched location, it is still obscuring the bottom
3399 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
3400 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
3401 *
3402 * In this test, we ensure that the event received by the bottom window has
3403 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
3404 */
3405TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
3406 constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
3407 constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
3408
3409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3410 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3411
3412 sp<FakeWindowHandle> slipperyExitWindow =
3413 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08003414 slipperyExitWindow->setTouchModal(false);
3415 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003416 // Make sure this one overlaps the bottom window
3417 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
3418 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
3419 // one. Windows with the same owner are not considered to be occluding each other.
3420 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
3421
3422 sp<FakeWindowHandle> slipperyEnterWindow =
3423 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
3424 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
3425
3426 mDispatcher->setInputWindows(
3427 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3428
3429 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
3430 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3431 ADISPLAY_ID_DEFAULT, {{50, 50}});
3432 mDispatcher->notifyMotion(&args);
3433 slipperyExitWindow->consumeMotionDown();
3434 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
3435 mDispatcher->setInputWindows(
3436 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
3437
3438 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3439 ADISPLAY_ID_DEFAULT, {{51, 51}});
3440 mDispatcher->notifyMotion(&args);
3441
3442 slipperyExitWindow->consumeMotionCancel();
3443
3444 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
3445 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
3446}
3447
Garfield Tan1c7bc862020-01-28 13:24:04 -08003448class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
3449protected:
3450 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
3451 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
3452
Chris Yea209fde2020-07-22 13:54:51 -07003453 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003454 sp<FakeWindowHandle> mWindow;
3455
3456 virtual void SetUp() override {
3457 mFakePolicy = new FakeInputDispatcherPolicy();
3458 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003459 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003460 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
3461 ASSERT_EQ(OK, mDispatcher->start());
3462
3463 setUpWindow();
3464 }
3465
3466 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07003467 mApp = std::make_shared<FakeApplicationHandle>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08003468 mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
3469
Vishnu Nair47074b82020-08-14 11:54:47 -07003470 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003471 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003472 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003473 mWindow->consumeFocusEvent(true);
3474 }
3475
Chris Ye2ad95392020-09-01 13:44:44 -07003476 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003477 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003478 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003479 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
3480 mDispatcher->notifyKey(&keyArgs);
3481
3482 // Window should receive key down event.
3483 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3484 }
3485
3486 void expectKeyRepeatOnce(int32_t repeatCount) {
3487 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
3488 InputEvent* repeatEvent = mWindow->consume();
3489 ASSERT_NE(nullptr, repeatEvent);
3490
3491 uint32_t eventType = repeatEvent->getType();
3492 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
3493
3494 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
3495 uint32_t eventAction = repeatKeyEvent->getAction();
3496 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
3497 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
3498 }
3499
Chris Ye2ad95392020-09-01 13:44:44 -07003500 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08003501 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07003502 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08003503 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
3504 mDispatcher->notifyKey(&keyArgs);
3505
3506 // Window should receive key down event.
3507 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
3508 0 /*expectedFlags*/);
3509 }
3510};
3511
3512TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07003513 sendAndConsumeKeyDown(1 /* deviceId */);
3514 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3515 expectKeyRepeatOnce(repeatCount);
3516 }
3517}
3518
3519TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
3520 sendAndConsumeKeyDown(1 /* deviceId */);
3521 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3522 expectKeyRepeatOnce(repeatCount);
3523 }
3524 sendAndConsumeKeyDown(2 /* deviceId */);
3525 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08003526 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3527 expectKeyRepeatOnce(repeatCount);
3528 }
3529}
3530
3531TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07003532 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003533 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07003534 sendAndConsumeKeyUp(1 /* deviceId */);
3535 mWindow->assertNoEvents();
3536}
3537
3538TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
3539 sendAndConsumeKeyDown(1 /* deviceId */);
3540 expectKeyRepeatOnce(1 /*repeatCount*/);
3541 sendAndConsumeKeyDown(2 /* deviceId */);
3542 expectKeyRepeatOnce(1 /*repeatCount*/);
3543 // Stale key up from device 1.
3544 sendAndConsumeKeyUp(1 /* deviceId */);
3545 // Device 2 is still down, keep repeating
3546 expectKeyRepeatOnce(2 /*repeatCount*/);
3547 expectKeyRepeatOnce(3 /*repeatCount*/);
3548 // Device 2 key up
3549 sendAndConsumeKeyUp(2 /* deviceId */);
3550 mWindow->assertNoEvents();
3551}
3552
3553TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
3554 sendAndConsumeKeyDown(1 /* deviceId */);
3555 expectKeyRepeatOnce(1 /*repeatCount*/);
3556 sendAndConsumeKeyDown(2 /* deviceId */);
3557 expectKeyRepeatOnce(1 /*repeatCount*/);
3558 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
3559 sendAndConsumeKeyUp(2 /* deviceId */);
3560 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08003561 mWindow->assertNoEvents();
3562}
3563
liushenxiang42232912021-05-21 20:24:09 +08003564TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
3565 sendAndConsumeKeyDown(DEVICE_ID);
3566 expectKeyRepeatOnce(1 /*repeatCount*/);
3567 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
3568 mDispatcher->notifyDeviceReset(&args);
3569 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
3570 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
3571 mWindow->assertNoEvents();
3572}
3573
Garfield Tan1c7bc862020-01-28 13:24:04 -08003574TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07003575 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003576 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3577 InputEvent* repeatEvent = mWindow->consume();
3578 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3579 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
3580 IdGenerator::getSource(repeatEvent->getId()));
3581 }
3582}
3583
3584TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07003585 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08003586
3587 std::unordered_set<int32_t> idSet;
3588 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
3589 InputEvent* repeatEvent = mWindow->consume();
3590 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
3591 int32_t id = repeatEvent->getId();
3592 EXPECT_EQ(idSet.end(), idSet.find(id));
3593 idSet.insert(id);
3594 }
3595}
3596
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003597/* Test InputDispatcher for MultiDisplay */
3598class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
3599public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003600 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003601 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08003602
Chris Yea209fde2020-07-22 13:54:51 -07003603 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003604 windowInPrimary =
3605 new FakeWindowHandle(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003606
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003607 // Set focus window for primary display, but focused display would be second one.
3608 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07003609 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003610 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003611 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003612 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08003613
Chris Yea209fde2020-07-22 13:54:51 -07003614 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003615 windowInSecondary =
3616 new FakeWindowHandle(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003617 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003618 // Set focus display to second one.
3619 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
3620 // Set focus window for second display.
3621 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07003622 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003623 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003624 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003625 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003626 }
3627
Prabir Pradhan3608aad2019-10-02 17:08:26 -07003628 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003629 InputDispatcherTest::TearDown();
3630
Chris Yea209fde2020-07-22 13:54:51 -07003631 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003632 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07003633 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003634 windowInSecondary.clear();
3635 }
3636
3637protected:
Chris Yea209fde2020-07-22 13:54:51 -07003638 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003639 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07003640 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003641 sp<FakeWindowHandle> windowInSecondary;
3642};
3643
3644TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
3645 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3647 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3648 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003649 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08003650 windowInSecondary->assertNoEvents();
3651
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003652 // 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 Hungb92218b2018-08-14 12:00:21 +08003656 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003657 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08003658}
3659
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003660TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08003661 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3663 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003664 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003665 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08003666 windowInSecondary->assertNoEvents();
3667
3668 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003670 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08003671 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003672 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08003673
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08003674 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00003675 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08003676
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003677 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003678 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
3679 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08003680
3681 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08003682 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003683 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08003684 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003685 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08003686 windowInSecondary->assertNoEvents();
3687}
3688
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003689// Test per-display input monitors for motion event.
3690TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08003691 FakeMonitorReceiver monitorInPrimary =
3692 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3693 FakeMonitorReceiver monitorInSecondary =
3694 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003695
3696 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3698 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003700 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003701 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003702 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003703 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003704
3705 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3707 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003709 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003710 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003711 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08003712 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003713
3714 // Test inject a non-pointer motion event.
3715 // If specific a display, it will dispatch to the focused window of particular display,
3716 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3718 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
3719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003720 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003721 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003722 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003723 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003724}
3725
3726// Test per-display input monitors for key event.
3727TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003728 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08003729 FakeMonitorReceiver monitorInPrimary =
3730 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3731 FakeMonitorReceiver monitorInSecondary =
3732 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003733
3734 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
3736 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003737 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08003738 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003739 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08003740 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08003741}
3742
Vishnu Nair958da932020-08-21 17:12:37 -07003743TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
3744 sp<FakeWindowHandle> secondWindowInPrimary =
3745 new FakeWindowHandle(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
3746 secondWindowInPrimary->setFocusable(true);
3747 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
3748 setFocusedWindow(secondWindowInPrimary);
3749 windowInPrimary->consumeFocusEvent(false);
3750 secondWindowInPrimary->consumeFocusEvent(true);
3751
3752 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
3754 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07003755 windowInPrimary->assertNoEvents();
3756 windowInSecondary->assertNoEvents();
3757 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3758}
3759
Arthur Hungdfd528e2021-12-08 13:23:04 +00003760TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
3761 FakeMonitorReceiver monitorInPrimary =
3762 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
3763 FakeMonitorReceiver monitorInSecondary =
3764 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
3765
3766 // Test touch down on primary display.
3767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3768 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3770 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3771 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3772
3773 // Test touch down on second display.
3774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3775 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
3776 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3777 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
3778 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
3779
3780 // Trigger cancel touch.
3781 mDispatcher->cancelCurrentTouch();
3782 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
3783 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
3784 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
3785 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
3786
3787 // Test inject a move motion event, no window/monitor should receive the event.
3788 ASSERT_EQ(InputEventInjectionResult::FAILED,
3789 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3790 ADISPLAY_ID_DEFAULT, {110, 200}))
3791 << "Inject motion event should return InputEventInjectionResult::FAILED";
3792 windowInPrimary->assertNoEvents();
3793 monitorInPrimary.assertNoEvents();
3794
3795 ASSERT_EQ(InputEventInjectionResult::FAILED,
3796 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3797 SECOND_DISPLAY_ID, {110, 200}))
3798 << "Inject motion event should return InputEventInjectionResult::FAILED";
3799 windowInSecondary->assertNoEvents();
3800 monitorInSecondary.assertNoEvents();
3801}
3802
Jackal Guof9696682018-10-05 12:23:23 +08003803class InputFilterTest : public InputDispatcherTest {
3804protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003805 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
3806 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08003807 NotifyMotionArgs motionArgs;
3808
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003809 motionArgs =
3810 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003811 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003812 motionArgs =
3813 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08003814 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003815 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003816 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003817 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
3818 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08003819 } else {
3820 mFakePolicy->assertFilterInputEventWasNotCalled();
3821 }
3822 }
3823
3824 void testNotifyKey(bool expectToBeFiltered) {
3825 NotifyKeyArgs keyArgs;
3826
3827 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3828 mDispatcher->notifyKey(&keyArgs);
3829 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
3830 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003831 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08003832
3833 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08003834 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08003835 } else {
3836 mFakePolicy->assertFilterInputEventWasNotCalled();
3837 }
3838 }
3839};
3840
3841// Test InputFilter for MotionEvent
3842TEST_F(InputFilterTest, MotionEvent_InputFilter) {
3843 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
3844 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3845 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3846
3847 // Enable InputFilter
3848 mDispatcher->setInputFilterEnabled(true);
3849 // Test touch on both primary and second display, and check if both events are filtered.
3850 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
3851 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
3852
3853 // Disable InputFilter
3854 mDispatcher->setInputFilterEnabled(false);
3855 // Test touch on both primary and second display, and check if both events aren't filtered.
3856 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
3857 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
3858}
3859
3860// Test InputFilter for KeyEvent
3861TEST_F(InputFilterTest, KeyEvent_InputFilter) {
3862 // Since the InputFilter is disabled by default, check if key event aren't filtered.
3863 testNotifyKey(/*expectToBeFiltered*/ false);
3864
3865 // Enable InputFilter
3866 mDispatcher->setInputFilterEnabled(true);
3867 // Send a key event, and check if it is filtered.
3868 testNotifyKey(/*expectToBeFiltered*/ true);
3869
3870 // Disable InputFilter
3871 mDispatcher->setInputFilterEnabled(false);
3872 // Send a key event, and check if it isn't filtered.
3873 testNotifyKey(/*expectToBeFiltered*/ false);
3874}
3875
Prabir Pradhan81420cc2021-09-06 10:28:50 -07003876// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
3877// logical display coordinate space.
3878TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
3879 ui::Transform firstDisplayTransform;
3880 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3881 ui::Transform secondDisplayTransform;
3882 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
3883
3884 std::vector<gui::DisplayInfo> displayInfos(2);
3885 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
3886 displayInfos[0].transform = firstDisplayTransform;
3887 displayInfos[1].displayId = SECOND_DISPLAY_ID;
3888 displayInfos[1].transform = secondDisplayTransform;
3889
3890 mDispatcher->onWindowInfosChanged({}, displayInfos);
3891
3892 // Enable InputFilter
3893 mDispatcher->setInputFilterEnabled(true);
3894
3895 // Ensure the correct transforms are used for the displays.
3896 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
3897 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
3898}
3899
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003900class InputFilterInjectionPolicyTest : public InputDispatcherTest {
3901protected:
3902 virtual void SetUp() override {
3903 InputDispatcherTest::SetUp();
3904
3905 /**
3906 * We don't need to enable input filter to test the injected event policy, but we enabled it
3907 * here to make the tests more realistic, since this policy only matters when inputfilter is
3908 * on.
3909 */
3910 mDispatcher->setInputFilterEnabled(true);
3911
3912 std::shared_ptr<InputApplicationHandle> application =
3913 std::make_shared<FakeApplicationHandle>();
3914 mWindow =
3915 new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT);
3916
3917 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3918 mWindow->setFocusable(true);
3919 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
3920 setFocusedWindow(mWindow);
3921 mWindow->consumeFocusEvent(true);
3922 }
3923
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003924 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3925 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003926 KeyEvent event;
3927
3928 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3929 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
3930 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
3931 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
3932 const int32_t additionalPolicyFlags =
3933 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
3934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3935 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3936 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3937 policyFlags | additionalPolicyFlags));
3938
3939 InputEvent* received = mWindow->consume();
3940 ASSERT_NE(nullptr, received);
3941 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003942 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
3943 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
3944 ASSERT_EQ(flags, keyEvent.getFlags());
3945 }
3946
3947 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
3948 int32_t flags) {
3949 MotionEvent event;
3950 PointerProperties pointerProperties[1];
3951 PointerCoords pointerCoords[1];
3952 pointerProperties[0].clear();
3953 pointerProperties[0].id = 0;
3954 pointerCoords[0].clear();
3955 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
3956 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
3957
3958 ui::Transform identityTransform;
3959 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3960 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
3961 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
3962 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
3963 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07003964 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07003965 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003966 /*pointerCount*/ 1, pointerProperties, pointerCoords);
3967
3968 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
3969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3970 mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
3971 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
3972 policyFlags | additionalPolicyFlags));
3973
3974 InputEvent* received = mWindow->consume();
3975 ASSERT_NE(nullptr, received);
3976 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
3977 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
3978 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
3979 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003980 }
3981
3982private:
3983 sp<FakeWindowHandle> mWindow;
3984};
3985
3986TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003987 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
3988 // filter. Without it, the event will no different from a regularly injected event, and the
3989 // injected device id will be overwritten.
3990 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3991 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003992}
3993
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003994TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00003995 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00003996 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
3997 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3998}
3999
4000TEST_F(InputFilterInjectionPolicyTest,
4001 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
4002 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
4003 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4004 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004005}
4006
4007TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
4008 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004009 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004010}
4011
chaviwfd6d3512019-03-25 13:23:49 -07004012class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004013 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07004014 InputDispatcherTest::SetUp();
4015
Chris Yea209fde2020-07-22 13:54:51 -07004016 std::shared_ptr<FakeApplicationHandle> application =
4017 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004018 mUnfocusedWindow =
4019 new FakeWindowHandle(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004020 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
4021 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4022 // window.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004023 mUnfocusedWindow->setTouchModal(false);
chaviwfd6d3512019-03-25 13:23:49 -07004024
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004025 mFocusedWindow =
4026 new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
4027 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004028 mFocusedWindow->setTouchModal(false);
chaviwfd6d3512019-03-25 13:23:49 -07004029
4030 // Set focused application.
4031 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004032 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07004033
4034 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00004035 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004036 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004037 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07004038 }
4039
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004040 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07004041 InputDispatcherTest::TearDown();
4042
4043 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004044 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07004045 }
4046
4047protected:
4048 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004049 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004050 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07004051};
4052
4053// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4054// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
4055// the onPointerDownOutsideFocus callback.
4056TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004058 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4059 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004060 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004061 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004062
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004063 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07004064 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
4065}
4066
4067// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
4068// DOWN on the window that doesn't have focus. Ensure no window received the
4069// onPointerDownOutsideFocus callback.
4070TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004072 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004073 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004074 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004075
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004076 ASSERT_TRUE(mDispatcher->waitForIdle());
4077 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004078}
4079
4080// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
4081// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
4082TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4084 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004085 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004086 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004087
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004088 ASSERT_TRUE(mDispatcher->waitForIdle());
4089 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004090}
4091
4092// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4093// DOWN on the window that already has focus. Ensure no window received the
4094// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004095TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004097 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004098 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004099 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004100 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004101
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004102 ASSERT_TRUE(mDispatcher->waitForIdle());
4103 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004104}
4105
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08004106// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
4107// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
4108TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
4109 const MotionEvent event =
4110 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4111 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
4112 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
4113 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
4114 .build();
4115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
4116 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4117 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
4118
4119 ASSERT_TRUE(mDispatcher->waitForIdle());
4120 mFakePolicy->assertOnPointerDownWasNotCalled();
4121 // Ensure that the unfocused window did not receive any FOCUS events.
4122 mUnfocusedWindow->assertNoEvents();
4123}
4124
chaviwaf87b3e2019-10-01 16:59:28 -07004125// These tests ensures we can send touch events to a single client when there are multiple input
4126// windows that point to the same client token.
4127class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
4128 virtual void SetUp() override {
4129 InputDispatcherTest::SetUp();
4130
Chris Yea209fde2020-07-22 13:54:51 -07004131 std::shared_ptr<FakeApplicationHandle> application =
4132 std::make_shared<FakeApplicationHandle>();
chaviwaf87b3e2019-10-01 16:59:28 -07004133 mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1",
4134 ADISPLAY_ID_DEFAULT);
4135 // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window.
4136 // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004137 mWindow1->setTouchModal(false);
4138 mWindow1->setSplitTouch(true);
chaviwaf87b3e2019-10-01 16:59:28 -07004139 mWindow1->setFrame(Rect(0, 0, 100, 100));
4140
4141 mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2",
4142 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004143 mWindow2->setTouchModal(false);
4144 mWindow2->setSplitTouch(true);
chaviwaf87b3e2019-10-01 16:59:28 -07004145 mWindow2->setFrame(Rect(100, 100, 200, 200));
4146
Arthur Hung72d8dc32020-03-28 00:48:39 +00004147 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07004148 }
4149
4150protected:
4151 sp<FakeWindowHandle> mWindow1;
4152 sp<FakeWindowHandle> mWindow2;
4153
4154 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05004155 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07004156 vec2 vals = windowInfo->transform.transform(point.x, point.y);
4157 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07004158 }
4159
4160 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
4161 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004162 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07004163 InputEvent* event = window->consume();
4164
4165 ASSERT_NE(nullptr, event) << name.c_str()
4166 << ": consumer should have returned non-NULL event.";
4167
4168 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
4169 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
4170 << " event, got " << inputEventTypeToString(event->getType()) << " event";
4171
4172 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004173 assertMotionAction(expectedAction, motionEvent.getAction());
chaviwaf87b3e2019-10-01 16:59:28 -07004174
4175 for (size_t i = 0; i < points.size(); i++) {
4176 float expectedX = points[i].x;
4177 float expectedY = points[i].y;
4178
4179 EXPECT_EQ(expectedX, motionEvent.getX(i))
4180 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
4181 << ", got " << motionEvent.getX(i);
4182 EXPECT_EQ(expectedY, motionEvent.getY(i))
4183 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
4184 << ", got " << motionEvent.getY(i);
4185 }
4186 }
chaviw9eaa22c2020-07-01 16:21:27 -07004187
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004188 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07004189 std::vector<PointF> expectedPoints) {
4190 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
4191 ADISPLAY_ID_DEFAULT, touchedPoints);
4192 mDispatcher->notifyMotion(&motionArgs);
4193
4194 // Always consume from window1 since it's the window that has the InputReceiver
4195 consumeMotionEvent(mWindow1, action, expectedPoints);
4196 }
chaviwaf87b3e2019-10-01 16:59:28 -07004197};
4198
4199TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
4200 // Touch Window 1
4201 PointF touchedPoint = {10, 10};
4202 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004203 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004204
4205 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07004206 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004207
4208 // Touch Window 2
4209 touchedPoint = {150, 150};
4210 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004211 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004212}
4213
chaviw9eaa22c2020-07-01 16:21:27 -07004214TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
4215 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07004216 mWindow2->setWindowScale(0.5f, 0.5f);
4217
4218 // Touch Window 1
4219 PointF touchedPoint = {10, 10};
4220 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004221 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004222 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07004223 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004224
4225 // Touch Window 2
4226 touchedPoint = {150, 150};
4227 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07004228 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
4229 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004230
chaviw9eaa22c2020-07-01 16:21:27 -07004231 // Update the transform so rotation is set
4232 mWindow2->setWindowTransform(0, -1, 1, 0);
4233 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
4234 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07004235}
4236
chaviw9eaa22c2020-07-01 16:21:27 -07004237TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004238 mWindow2->setWindowScale(0.5f, 0.5f);
4239
4240 // Touch Window 1
4241 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4242 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004243 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004244
4245 // Touch Window 2
4246 int32_t actionPointerDown =
4247 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07004248 touchedPoints.push_back(PointF{150, 150});
4249 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
4250 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004251
chaviw9eaa22c2020-07-01 16:21:27 -07004252 // Release Window 2
4253 int32_t actionPointerUp =
4254 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4255 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
4256 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004257
chaviw9eaa22c2020-07-01 16:21:27 -07004258 // Update the transform so rotation is set for Window 2
4259 mWindow2->setWindowTransform(0, -1, 1, 0);
4260 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
4261 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004262}
4263
chaviw9eaa22c2020-07-01 16:21:27 -07004264TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004265 mWindow2->setWindowScale(0.5f, 0.5f);
4266
4267 // Touch Window 1
4268 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4269 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004270 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004271
4272 // Touch Window 2
4273 int32_t actionPointerDown =
4274 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07004275 touchedPoints.push_back(PointF{150, 150});
4276 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004277
chaviw9eaa22c2020-07-01 16:21:27 -07004278 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004279
4280 // Move both windows
4281 touchedPoints = {{20, 20}, {175, 175}};
4282 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4283 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4284
chaviw9eaa22c2020-07-01 16:21:27 -07004285 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004286
chaviw9eaa22c2020-07-01 16:21:27 -07004287 // Release Window 2
4288 int32_t actionPointerUp =
4289 AMOTION_EVENT_ACTION_POINTER_UP + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4290 touchAndAssertPositions(actionPointerUp, touchedPoints, expectedPoints);
4291 expectedPoints.pop_back();
4292
4293 // Touch Window 2
4294 mWindow2->setWindowTransform(0, -1, 1, 0);
4295 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
4296 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
4297
4298 // Move both windows
4299 touchedPoints = {{20, 20}, {175, 175}};
4300 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4301 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4302
4303 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004304}
4305
4306TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
4307 mWindow1->setWindowScale(0.5f, 0.5f);
4308
4309 // Touch Window 1
4310 std::vector<PointF> touchedPoints = {PointF{10, 10}};
4311 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07004312 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004313
4314 // Touch Window 2
4315 int32_t actionPointerDown =
4316 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
chaviw9eaa22c2020-07-01 16:21:27 -07004317 touchedPoints.push_back(PointF{150, 150});
4318 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004319
chaviw9eaa22c2020-07-01 16:21:27 -07004320 touchAndAssertPositions(actionPointerDown, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004321
4322 // Move both windows
4323 touchedPoints = {{20, 20}, {175, 175}};
4324 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
4325 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
4326
chaviw9eaa22c2020-07-01 16:21:27 -07004327 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00004328}
4329
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004330class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
4331 virtual void SetUp() override {
4332 InputDispatcherTest::SetUp();
4333
Chris Yea209fde2020-07-22 13:54:51 -07004334 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004335 mApplication->setDispatchingTimeout(20ms);
4336 mWindow =
4337 new FakeWindowHandle(mApplication, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
4338 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004339 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07004340 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004341 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4342 // window.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004343 mWindow->setTouchModal(false);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004344
4345 // Set focused application.
4346 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
4347
4348 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004349 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004350 mWindow->consumeFocusEvent(true);
4351 }
4352
4353 virtual void TearDown() override {
4354 InputDispatcherTest::TearDown();
4355 mWindow.clear();
4356 }
4357
4358protected:
Chris Yea209fde2020-07-22 13:54:51 -07004359 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004360 sp<FakeWindowHandle> mWindow;
4361 static constexpr PointF WINDOW_LOCATION = {20, 20};
4362
4363 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004365 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4366 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004368 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4369 WINDOW_LOCATION));
4370 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004371
4372 sp<FakeWindowHandle> addSpyWindow() {
4373 sp<FakeWindowHandle> spy =
4374 new FakeWindowHandle(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4375 spy->setTrustedOverlay(true);
4376 spy->setFocusable(false);
4377 spy->setInputFeatures(WindowInfo::Feature::SPY);
4378 spy->setDispatchingTimeout(30ms);
4379 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
4380 return spy;
4381 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004382};
4383
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004384// Send a tap and respond, which should not cause an ANR.
4385TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
4386 tapOnWindow();
4387 mWindow->consumeMotionDown();
4388 mWindow->consumeMotionUp();
4389 ASSERT_TRUE(mDispatcher->waitForIdle());
4390 mFakePolicy->assertNotifyAnrWasNotCalled();
4391}
4392
4393// Send a regular key and respond, which should not cause an ANR.
4394TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004396 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
4397 ASSERT_TRUE(mDispatcher->waitForIdle());
4398 mFakePolicy->assertNotifyAnrWasNotCalled();
4399}
4400
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004401TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
4402 mWindow->setFocusable(false);
4403 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4404 mWindow->consumeFocusEvent(false);
4405
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004406 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004407 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004408 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
4409 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05004411 // Key will not go to window because we have no focused window.
4412 // The 'no focused window' ANR timer should start instead.
4413
4414 // Now, the focused application goes away.
4415 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
4416 // The key should get dropped and there should be no ANR.
4417
4418 ASSERT_TRUE(mDispatcher->waitForIdle());
4419 mFakePolicy->assertNotifyAnrWasNotCalled();
4420}
4421
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004422// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004423// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
4424// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004425TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004427 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4428 WINDOW_LOCATION));
4429
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004430 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
4431 ASSERT_TRUE(sequenceNum);
4432 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004433 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004434
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004435 mWindow->finishEvent(*sequenceNum);
4436 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4437 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004438 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004439 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004440}
4441
4442// Send a key to the app and have the app not respond right away.
4443TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
4444 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004446 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
4447 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004448 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004449 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004450 ASSERT_TRUE(mDispatcher->waitForIdle());
4451}
4452
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004453// We have a focused application, but no focused window
4454TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004455 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004456 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4457 mWindow->consumeFocusEvent(false);
4458
4459 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004461 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4462 WINDOW_LOCATION));
4463 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
4464 mDispatcher->waitForIdle();
4465 mFakePolicy->assertNotifyAnrWasNotCalled();
4466
4467 // Once a focused event arrives, we get an ANR for this application
4468 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4469 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004470 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004471 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004472 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004473 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004474 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004475 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004476 ASSERT_TRUE(mDispatcher->waitForIdle());
4477}
4478
4479// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004480// Make sure that we don't notify policy twice about the same ANR.
4481TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004482 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4484 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004485
4486 // Once a focused event arrives, we get an ANR for this application
4487 // We specify the injection timeout to be smaller than the application timeout, to ensure that
4488 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004489 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004490 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004491 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004492 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004493 const std::chrono::duration appTimeout =
4494 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004495 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004496
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004497 std::this_thread::sleep_for(appTimeout);
4498 // ANR should not be raised again. It is up to policy to do that if it desires.
4499 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004500
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004501 // If we now get a focused window, the ANR should stop, but the policy handles that via
4502 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004503 ASSERT_TRUE(mDispatcher->waitForIdle());
4504}
4505
4506// We have a focused application, but no focused window
4507TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07004508 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004509 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4510 mWindow->consumeFocusEvent(false);
4511
4512 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004513 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004514 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004515 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4516 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004517
4518 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004519 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004520
4521 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004522 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004523 ASSERT_TRUE(mDispatcher->waitForIdle());
4524 mWindow->assertNoEvents();
4525}
4526
4527/**
4528 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
4529 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
4530 * If we process 1 of the events, but ANR on the second event with the same timestamp,
4531 * the ANR mechanism should still work.
4532 *
4533 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
4534 * DOWN event, while not responding on the second one.
4535 */
4536TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
4537 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
4538 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4539 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4540 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4541 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004542 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004543
4544 // Now send ACTION_UP, with identical timestamp
4545 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4546 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
4547 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
4548 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004549 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004550
4551 // We have now sent down and up. Let's consume first event and then ANR on the second.
4552 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4553 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004554 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004555}
4556
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004557// A spy window can receive an ANR
4558TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
4559 sp<FakeWindowHandle> spy = addSpyWindow();
4560
4561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4562 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4563 WINDOW_LOCATION));
4564 mWindow->consumeMotionDown();
4565
4566 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
4567 ASSERT_TRUE(sequenceNum);
4568 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
4569 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy->getToken());
4570
4571 spy->finishEvent(*sequenceNum);
4572 spy->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
4573 0 /*flags*/);
4574 ASSERT_TRUE(mDispatcher->waitForIdle());
4575 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken());
4576}
4577
4578// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004579// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004580TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
4581 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004582
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4584 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004585 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004587
4588 // Stuck on the ACTION_UP
4589 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004590 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004591
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004592 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004593 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004594 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4595 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004596
4597 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4598 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004599 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004600 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004601 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004602}
4603
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004604// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004605// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004606TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
4607 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004608
4609 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004610 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4611 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004612
4613 mWindow->consumeMotionDown();
4614 // Stuck on the ACTION_UP
4615 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004616 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004617
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004618 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004619 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004620 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4621 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004622
4623 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
4624 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004625 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004626 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004627 spy->assertNoEvents();
4628}
4629
4630TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
4631 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
4632
4633 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4634
4635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4636 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4637 WINDOW_LOCATION));
4638
4639 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4640 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
4641 ASSERT_TRUE(consumeSeq);
4642
4643 mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(30ms);
4644
4645 monitor.finishEvent(*consumeSeq);
4646 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4647
4648 ASSERT_TRUE(mDispatcher->waitForIdle());
4649 mFakePolicy->assertNotifyMonitorResponsiveWasCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004650}
4651
4652// If a window is unresponsive, then you get anr. if the window later catches up and starts to
4653// process events, you don't get an anr. When the window later becomes unresponsive again, you
4654// get an ANR again.
4655// 1. tap -> block on ACTION_UP -> receive ANR
4656// 2. consume all pending events (= queue becomes healthy again)
4657// 3. tap again -> block on ACTION_UP again -> receive ANR second time
4658TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
4659 tapOnWindow();
4660
4661 mWindow->consumeMotionDown();
4662 // Block on ACTION_UP
4663 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004664 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004665 mWindow->consumeMotionUp(); // Now the connection should be healthy again
4666 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004667 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004668 mWindow->assertNoEvents();
4669
4670 tapOnWindow();
4671 mWindow->consumeMotionDown();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004672 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004673 mWindow->consumeMotionUp();
4674
4675 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004676 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004677 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004678 mWindow->assertNoEvents();
4679}
4680
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004681// If a connection remains unresponsive for a while, make sure policy is only notified once about
4682// it.
4683TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004685 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4686 WINDOW_LOCATION));
4687
4688 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004689 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004690 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004691 // 'notifyConnectionUnresponsive' should only be called once per connection
4692 mFakePolicy->assertNotifyAnrWasNotCalled();
4693 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004694 mWindow->consumeMotionDown();
4695 mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL,
4696 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4697 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004698 mDispatcher->waitForIdle();
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004699 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004700 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004701}
4702
4703/**
4704 * If a window is processing a motion event, and then a key event comes in, the key event should
4705 * not to to the focused window until the motion is processed.
4706 *
4707 * Warning!!!
4708 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4709 * and the injection timeout that we specify when injecting the key.
4710 * We must have the injection timeout (10ms) be smaller than
4711 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4712 *
4713 * If that value changes, this test should also change.
4714 */
4715TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
4716 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4718
4719 tapOnWindow();
4720 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4721 ASSERT_TRUE(downSequenceNum);
4722 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4723 ASSERT_TRUE(upSequenceNum);
4724 // Don't finish the events yet, and send a key
4725 // Injection will "succeed" because we will eventually give up and send the key to the focused
4726 // window even if motions are still being processed. But because the injection timeout is short,
4727 // we will receive INJECTION_TIMED_OUT as the result.
4728
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004729 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004730 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004731 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
4732 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004733 // Key will not be sent to the window, yet, because the window is still processing events
4734 // and the key remains pending, waiting for the touch events to be processed
4735 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4736 ASSERT_FALSE(keySequenceNum);
4737
4738 std::this_thread::sleep_for(500ms);
4739 // if we wait long enough though, dispatcher will give up, and still send the key
4740 // to the focused window, even though we have not yet finished the motion event
4741 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4742 mWindow->finishEvent(*downSequenceNum);
4743 mWindow->finishEvent(*upSequenceNum);
4744}
4745
4746/**
4747 * If a window is processing a motion event, and then a key event comes in, the key event should
4748 * not go to the focused window until the motion is processed.
4749 * If then a new motion comes in, then the pending key event should be going to the currently
4750 * focused window right away.
4751 */
4752TEST_F(InputDispatcherSingleWindowAnr,
4753 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
4754 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
4755 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4756
4757 tapOnWindow();
4758 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
4759 ASSERT_TRUE(downSequenceNum);
4760 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
4761 ASSERT_TRUE(upSequenceNum);
4762 // Don't finish the events yet, and send a key
4763 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004765 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004766 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004767 // At this point, key is still pending, and should not be sent to the application yet.
4768 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
4769 ASSERT_FALSE(keySequenceNum);
4770
4771 // Now tap down again. It should cause the pending key to go to the focused window right away.
4772 tapOnWindow();
4773 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
4774 // the other events yet. We can finish events in any order.
4775 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
4776 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
4777 mWindow->consumeMotionDown();
4778 mWindow->consumeMotionUp();
4779 mWindow->assertNoEvents();
4780}
4781
4782class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
4783 virtual void SetUp() override {
4784 InputDispatcherTest::SetUp();
4785
Chris Yea209fde2020-07-22 13:54:51 -07004786 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004787 mApplication->setDispatchingTimeout(10ms);
4788 mUnfocusedWindow =
4789 new FakeWindowHandle(mApplication, mDispatcher, "Unfocused", ADISPLAY_ID_DEFAULT);
4790 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
4791 // Adding FLAG_NOT_TOUCH_MODAL to ensure taps outside this window are not sent to this
4792 // window.
4793 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004794 mUnfocusedWindow->setTouchModal(false);
4795 mUnfocusedWindow->setSplitTouch(true);
4796 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004797
4798 mFocusedWindow =
4799 new FakeWindowHandle(mApplication, mDispatcher, "Focused", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05004800 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004801 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004802 mFocusedWindow->setTouchModal(false);
4803 mFocusedWindow->setSplitTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004804
4805 // Set focused application.
4806 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07004807 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004808
4809 // Expect one focus window exist in display.
4810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004811 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004812 mFocusedWindow->consumeFocusEvent(true);
4813 }
4814
4815 virtual void TearDown() override {
4816 InputDispatcherTest::TearDown();
4817
4818 mUnfocusedWindow.clear();
4819 mFocusedWindow.clear();
4820 }
4821
4822protected:
Chris Yea209fde2020-07-22 13:54:51 -07004823 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004824 sp<FakeWindowHandle> mUnfocusedWindow;
4825 sp<FakeWindowHandle> mFocusedWindow;
4826 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
4827 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
4828 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
4829
4830 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
4831
4832 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
4833
4834private:
4835 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004837 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4838 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004840 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4841 location));
4842 }
4843};
4844
4845// If we have 2 windows that are both unresponsive, the one with the shortest timeout
4846// should be ANR'd first.
4847TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004849 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4850 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004851 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004852 mFocusedWindow->consumeMotionDown();
4853 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4854 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4855 // We consumed all events, so no ANR
4856 ASSERT_TRUE(mDispatcher->waitForIdle());
4857 mFakePolicy->assertNotifyAnrWasNotCalled();
4858
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004860 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4861 FOCUSED_WINDOW_LOCATION));
4862 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
4863 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004864
4865 const std::chrono::duration timeout =
4866 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004867 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004868 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
4869 // sequence to make it consistent
4870 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004871 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004872 mFocusedWindow->consumeMotionDown();
4873 // This cancel is generated because the connection was unresponsive
4874 mFocusedWindow->consumeMotionCancel();
4875 mFocusedWindow->assertNoEvents();
4876 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004877 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004878 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004879 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004880}
4881
4882// If we have 2 windows with identical timeouts that are both unresponsive,
4883// it doesn't matter which order they should have ANR.
4884// But we should receive ANR for both.
4885TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
4886 // Set the timeout for unfocused window to match the focused window
4887 mUnfocusedWindow->setDispatchingTimeout(10ms);
4888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4889
4890 tapOnFocusedWindow();
4891 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004892 sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms);
4893 sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004894
4895 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004896 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
4897 mFocusedWindow->getToken() == anrConnectionToken2);
4898 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
4899 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004900
4901 ASSERT_TRUE(mDispatcher->waitForIdle());
4902 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004903
4904 mFocusedWindow->consumeMotionDown();
4905 mFocusedWindow->consumeMotionUp();
4906 mUnfocusedWindow->consumeMotionOutside();
4907
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004908 sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken();
4909 sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004910
4911 // Both applications should be marked as responsive, in any order
4912 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
4913 mFocusedWindow->getToken() == responsiveToken2);
4914 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
4915 mUnfocusedWindow->getToken() == responsiveToken2);
4916 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004917}
4918
4919// If a window is already not responding, the second tap on the same window should be ignored.
4920// We should also log an error to account for the dropped event (not tested here).
4921// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
4922TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
4923 tapOnFocusedWindow();
4924 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
4925 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
4926 // Receive the events, but don't respond
4927 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
4928 ASSERT_TRUE(downEventSequenceNum);
4929 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
4930 ASSERT_TRUE(upEventSequenceNum);
4931 const std::chrono::duration timeout =
4932 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004933 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004934
4935 // Tap once again
4936 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004937 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004938 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4939 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004940 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004941 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4942 FOCUSED_WINDOW_LOCATION));
4943 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
4944 // valid touch target
4945 mUnfocusedWindow->assertNoEvents();
4946
4947 // Consume the first tap
4948 mFocusedWindow->finishEvent(*downEventSequenceNum);
4949 mFocusedWindow->finishEvent(*upEventSequenceNum);
4950 ASSERT_TRUE(mDispatcher->waitForIdle());
4951 // The second tap did not go to the focused window
4952 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05004953 // Since all events are finished, connection should be deemed healthy again
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00004954 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004955 mFakePolicy->assertNotifyAnrWasNotCalled();
4956}
4957
4958// If you tap outside of all windows, there will not be ANR
4959TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004960 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004961 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4962 LOCATION_OUTSIDE_ALL_WINDOWS));
4963 ASSERT_TRUE(mDispatcher->waitForIdle());
4964 mFakePolicy->assertNotifyAnrWasNotCalled();
4965}
4966
4967// Since the focused window is paused, tapping on it should not produce any events
4968TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
4969 mFocusedWindow->setPaused(true);
4970 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
4971
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004972 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004973 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4974 FOCUSED_WINDOW_LOCATION));
4975
4976 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
4977 ASSERT_TRUE(mDispatcher->waitForIdle());
4978 // Should not ANR because the window is paused, and touches shouldn't go to it
4979 mFakePolicy->assertNotifyAnrWasNotCalled();
4980
4981 mFocusedWindow->assertNoEvents();
4982 mUnfocusedWindow->assertNoEvents();
4983}
4984
4985/**
4986 * If a window is processing a motion event, and then a key event comes in, the key event should
4987 * not to to the focused window until the motion is processed.
4988 * If a different window becomes focused at this time, the key should go to that window instead.
4989 *
4990 * Warning!!!
4991 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
4992 * and the injection timeout that we specify when injecting the key.
4993 * We must have the injection timeout (10ms) be smaller than
4994 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
4995 *
4996 * If that value changes, this test should also change.
4997 */
4998TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
4999 // Set a long ANR timeout to prevent it from triggering
5000 mFocusedWindow->setDispatchingTimeout(2s);
5001 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5002
5003 tapOnUnfocusedWindow();
5004 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
5005 ASSERT_TRUE(downSequenceNum);
5006 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
5007 ASSERT_TRUE(upSequenceNum);
5008 // Don't finish the events yet, and send a key
5009 // Injection will succeed because we will eventually give up and send the key to the focused
5010 // window even if motions are still being processed.
5011
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005012 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005013 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005014 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
5015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005016 // Key will not be sent to the window, yet, because the window is still processing events
5017 // and the key remains pending, waiting for the touch events to be processed
5018 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
5019 ASSERT_FALSE(keySequenceNum);
5020
5021 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07005022 mFocusedWindow->setFocusable(false);
5023 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005025 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005026
5027 // Focus events should precede the key events
5028 mUnfocusedWindow->consumeFocusEvent(true);
5029 mFocusedWindow->consumeFocusEvent(false);
5030
5031 // Finish the tap events, which should unblock dispatcher
5032 mUnfocusedWindow->finishEvent(*downSequenceNum);
5033 mUnfocusedWindow->finishEvent(*upSequenceNum);
5034
5035 // Now that all queues are cleared and no backlog in the connections, the key event
5036 // can finally go to the newly focused "mUnfocusedWindow".
5037 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5038 mFocusedWindow->assertNoEvents();
5039 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005040 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005041}
5042
5043// When the touch stream is split across 2 windows, and one of them does not respond,
5044// then ANR should be raised and the touch should be canceled for the unresponsive window.
5045// The other window should not be affected by that.
5046TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
5047 // Touch Window 1
5048 NotifyMotionArgs motionArgs =
5049 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5050 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
5051 mDispatcher->notifyMotion(&motionArgs);
5052 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5053 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5054
5055 // Touch Window 2
5056 int32_t actionPointerDown =
5057 AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
5058
5059 motionArgs =
5060 generateMotionArgs(actionPointerDown, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5061 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
5062 mDispatcher->notifyMotion(&motionArgs);
5063
5064 const std::chrono::duration timeout =
5065 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00005066 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005067
5068 mUnfocusedWindow->consumeMotionDown();
5069 mFocusedWindow->consumeMotionDown();
5070 // Focused window may or may not receive ACTION_MOVE
5071 // But it should definitely receive ACTION_CANCEL due to the ANR
5072 InputEvent* event;
5073 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
5074 ASSERT_TRUE(moveOrCancelSequenceNum);
5075 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
5076 ASSERT_NE(nullptr, event);
5077 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
5078 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5079 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
5080 mFocusedWindow->consumeMotionCancel();
5081 } else {
5082 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
5083 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005084 ASSERT_TRUE(mDispatcher->waitForIdle());
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +00005085 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005086
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005087 mUnfocusedWindow->assertNoEvents();
5088 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005089 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005090}
5091
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005092/**
5093 * If we have no focused window, and a key comes in, we start the ANR timer.
5094 * The focused application should add a focused window before the timer runs out to prevent ANR.
5095 *
5096 * If the user touches another application during this time, the key should be dropped.
5097 * Next, if a new focused window comes in, without toggling the focused application,
5098 * then no ANR should occur.
5099 *
5100 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
5101 * but in some cases the policy may not update the focused application.
5102 */
5103TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
5104 std::shared_ptr<FakeApplicationHandle> focusedApplication =
5105 std::make_shared<FakeApplicationHandle>();
5106 focusedApplication->setDispatchingTimeout(60ms);
5107 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
5108 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
5109 mFocusedWindow->setFocusable(false);
5110
5111 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5112 mFocusedWindow->consumeFocusEvent(false);
5113
5114 // Send a key. The ANR timer should start because there is no focused window.
5115 // 'focusedApplication' will get blamed if this timer completes.
5116 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005117 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005118 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005119 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
5120 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005122
5123 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
5124 // then the injected touches won't cause the focused event to get dropped.
5125 // The dispatcher only checks for whether the queue should be pruned upon queueing.
5126 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
5127 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
5128 // For this test, it means that the key would get delivered to the window once it becomes
5129 // focused.
5130 std::this_thread::sleep_for(10ms);
5131
5132 // Touch unfocused window. This should force the pending key to get dropped.
5133 NotifyMotionArgs motionArgs =
5134 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5135 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
5136 mDispatcher->notifyMotion(&motionArgs);
5137
5138 // We do not consume the motion right away, because that would require dispatcher to first
5139 // process (== drop) the key event, and by that time, ANR will be raised.
5140 // Set the focused window first.
5141 mFocusedWindow->setFocusable(true);
5142 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5143 setFocusedWindow(mFocusedWindow);
5144 mFocusedWindow->consumeFocusEvent(true);
5145 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
5146 // to another application. This could be a bug / behaviour in the policy.
5147
5148 mUnfocusedWindow->consumeMotionDown();
5149
5150 ASSERT_TRUE(mDispatcher->waitForIdle());
5151 // Should not ANR because we actually have a focused window. It was just added too slowly.
5152 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
5153}
5154
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005155// These tests ensure we cannot send touch events to a window that's positioned behind a window
5156// that has feature NO_INPUT_CHANNEL.
5157// Layout:
5158// Top (closest to user)
5159// mNoInputWindow (above all windows)
5160// mBottomWindow
5161// Bottom (furthest from user)
5162class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
5163 virtual void SetUp() override {
5164 InputDispatcherTest::SetUp();
5165
5166 mApplication = std::make_shared<FakeApplicationHandle>();
5167 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
5168 "Window without input channel", ADISPLAY_ID_DEFAULT,
5169 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
5170
chaviw3277faf2021-05-19 16:45:23 -05005171 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005172 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
5173 // It's perfectly valid for this window to not have an associated input channel
5174
5175 mBottomWindow = new FakeWindowHandle(mApplication, mDispatcher, "Bottom window",
5176 ADISPLAY_ID_DEFAULT);
5177 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
5178
5179 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
5180 }
5181
5182protected:
5183 std::shared_ptr<FakeApplicationHandle> mApplication;
5184 sp<FakeWindowHandle> mNoInputWindow;
5185 sp<FakeWindowHandle> mBottomWindow;
5186};
5187
5188TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
5189 PointF touchedPoint = {10, 10};
5190
5191 NotifyMotionArgs motionArgs =
5192 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5193 ADISPLAY_ID_DEFAULT, {touchedPoint});
5194 mDispatcher->notifyMotion(&motionArgs);
5195
5196 mNoInputWindow->assertNoEvents();
5197 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
5198 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
5199 // and therefore should prevent mBottomWindow from receiving touches
5200 mBottomWindow->assertNoEvents();
5201}
5202
5203/**
5204 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
5205 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
5206 */
5207TEST_F(InputDispatcherMultiWindowOcclusionTests,
5208 NoInputChannelFeature_DropsTouchesWithValidChannel) {
5209 mNoInputWindow = new FakeWindowHandle(mApplication, mDispatcher,
5210 "Window with input channel and NO_INPUT_CHANNEL",
5211 ADISPLAY_ID_DEFAULT);
5212
chaviw3277faf2021-05-19 16:45:23 -05005213 mNoInputWindow->setInputFeatures(WindowInfo::Feature::NO_INPUT_CHANNEL);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05005214 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
5215 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
5216
5217 PointF touchedPoint = {10, 10};
5218
5219 NotifyMotionArgs motionArgs =
5220 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5221 ADISPLAY_ID_DEFAULT, {touchedPoint});
5222 mDispatcher->notifyMotion(&motionArgs);
5223
5224 mNoInputWindow->assertNoEvents();
5225 mBottomWindow->assertNoEvents();
5226}
5227
Vishnu Nair958da932020-08-21 17:12:37 -07005228class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
5229protected:
5230 std::shared_ptr<FakeApplicationHandle> mApp;
5231 sp<FakeWindowHandle> mWindow;
5232 sp<FakeWindowHandle> mMirror;
5233
5234 virtual void SetUp() override {
5235 InputDispatcherTest::SetUp();
5236 mApp = std::make_shared<FakeApplicationHandle>();
5237 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5238 mMirror = new FakeWindowHandle(mApp, mDispatcher, "TestWindowMirror", ADISPLAY_ID_DEFAULT,
5239 mWindow->getToken());
5240 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5241 mWindow->setFocusable(true);
5242 mMirror->setFocusable(true);
5243 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5244 }
5245};
5246
5247TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
5248 // Request focus on a mirrored window
5249 setFocusedWindow(mMirror);
5250
5251 // window gets focused
5252 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5254 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005255 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
5256}
5257
5258// A focused & mirrored window remains focused only if the window and its mirror are both
5259// focusable.
5260TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
5261 setFocusedWindow(mMirror);
5262
5263 // window gets focused
5264 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5266 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005267 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5269 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005270 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5271
5272 mMirror->setFocusable(false);
5273 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5274
5275 // window loses focus since one of the windows associated with the token in not focusable
5276 mWindow->consumeFocusEvent(false);
5277
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005278 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5279 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005280 mWindow->assertNoEvents();
5281}
5282
5283// A focused & mirrored window remains focused until the window and its mirror both become
5284// invisible.
5285TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
5286 setFocusedWindow(mMirror);
5287
5288 // window gets focused
5289 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5291 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005292 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5294 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005295 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5296
5297 mMirror->setVisible(false);
5298 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5299
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5301 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005302 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5304 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005305 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5306
5307 mWindow->setVisible(false);
5308 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5309
5310 // window loses focus only after all windows associated with the token become invisible.
5311 mWindow->consumeFocusEvent(false);
5312
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005313 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5314 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005315 mWindow->assertNoEvents();
5316}
5317
5318// A focused & mirrored window remains focused until both windows are removed.
5319TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
5320 setFocusedWindow(mMirror);
5321
5322 // window gets focused
5323 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5325 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005326 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5328 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005329 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5330
5331 // single window is removed but the window token remains focused
5332 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
5333
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5335 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005336 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
5338 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005339 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
5340
5341 // Both windows are removed
5342 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5343 mWindow->consumeFocusEvent(false);
5344
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005345 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5346 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005347 mWindow->assertNoEvents();
5348}
5349
5350// Focus request can be pending until one window becomes visible.
5351TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
5352 // Request focus on an invisible mirror.
5353 mWindow->setVisible(false);
5354 mMirror->setVisible(false);
5355 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5356 setFocusedWindow(mMirror);
5357
5358 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07005360 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005361 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005362
5363 mMirror->setVisible(true);
5364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
5365
5366 // window gets focused
5367 mWindow->consumeFocusEvent(true);
5368 // window gets the pending key event
5369 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5370}
Prabir Pradhan99987712020-11-10 18:43:05 -08005371
5372class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
5373protected:
5374 std::shared_ptr<FakeApplicationHandle> mApp;
5375 sp<FakeWindowHandle> mWindow;
5376 sp<FakeWindowHandle> mSecondWindow;
5377
5378 void SetUp() override {
5379 InputDispatcherTest::SetUp();
5380 mApp = std::make_shared<FakeApplicationHandle>();
5381 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5382 mWindow->setFocusable(true);
5383 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5384 mSecondWindow->setFocusable(true);
5385
5386 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5387 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5388
5389 setFocusedWindow(mWindow);
5390 mWindow->consumeFocusEvent(true);
5391 }
5392
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005393 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
5394 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005395 mDispatcher->notifyPointerCaptureChanged(&args);
5396 }
5397
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005398 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
5399 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08005400 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005401 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
5402 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005403 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005404 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08005405 }
5406};
5407
5408TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
5409 // Ensure that capture cannot be obtained for unfocused windows.
5410 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
5411 mFakePolicy->assertSetPointerCaptureNotCalled();
5412 mSecondWindow->assertNoEvents();
5413
5414 // Ensure that capture can be enabled from the focus window.
5415 requestAndVerifyPointerCapture(mWindow, true);
5416
5417 // Ensure that capture cannot be disabled from a window that does not have capture.
5418 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
5419 mFakePolicy->assertSetPointerCaptureNotCalled();
5420
5421 // Ensure that capture can be disabled from the window with capture.
5422 requestAndVerifyPointerCapture(mWindow, false);
5423}
5424
5425TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005426 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005427
5428 setFocusedWindow(mSecondWindow);
5429
5430 // Ensure that the capture disabled event was sent first.
5431 mWindow->consumeCaptureEvent(false);
5432 mWindow->consumeFocusEvent(false);
5433 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005434 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005435
5436 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005437 notifyPointerCaptureChanged({});
5438 notifyPointerCaptureChanged(request);
5439 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08005440 mWindow->assertNoEvents();
5441 mSecondWindow->assertNoEvents();
5442 mFakePolicy->assertSetPointerCaptureNotCalled();
5443}
5444
5445TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005446 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08005447
5448 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005449 notifyPointerCaptureChanged({});
5450 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08005451
5452 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005453 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08005454 mWindow->consumeCaptureEvent(false);
5455 mWindow->assertNoEvents();
5456}
5457
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005458TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
5459 requestAndVerifyPointerCapture(mWindow, true);
5460
5461 // The first window loses focus.
5462 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005463 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005464 mWindow->consumeCaptureEvent(false);
5465
5466 // Request Pointer Capture from the second window before the notification from InputReader
5467 // arrives.
5468 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005469 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005470
5471 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005472 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005473
5474 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005475 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08005476
5477 mSecondWindow->consumeFocusEvent(true);
5478 mSecondWindow->consumeCaptureEvent(true);
5479}
5480
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00005481TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
5482 // App repeatedly enables and disables capture.
5483 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5484 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5485 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
5486 mFakePolicy->assertSetPointerCaptureCalled(false);
5487 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
5488 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
5489
5490 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
5491 // first request is now stale, this should do nothing.
5492 notifyPointerCaptureChanged(firstRequest);
5493 mWindow->assertNoEvents();
5494
5495 // InputReader notifies that the second request was enabled.
5496 notifyPointerCaptureChanged(secondRequest);
5497 mWindow->consumeCaptureEvent(true);
5498}
5499
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005500class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
5501protected:
5502 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00005503
5504 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
5505 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
5506
5507 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
5508 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5509
5510 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
5511 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
5512 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
5513 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
5514 MAXIMUM_OBSCURING_OPACITY);
5515
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005516 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005517 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005518 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005519
5520 sp<FakeWindowHandle> mTouchWindow;
5521
5522 virtual void SetUp() override {
5523 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005524 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005525 mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
5526 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
5527 }
5528
5529 virtual void TearDown() override {
5530 InputDispatcherTest::TearDown();
5531 mTouchWindow.clear();
5532 }
5533
chaviw3277faf2021-05-19 16:45:23 -05005534 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
5535 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005536 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005537 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005538 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005539 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005540 return window;
5541 }
5542
5543 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
5544 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
5545 sp<FakeWindowHandle> window =
5546 new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
5547 // Generate an arbitrary PID based on the UID
5548 window->setOwnerInfo(1777 + (uid % 10000), uid);
5549 return window;
5550 }
5551
5552 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
5553 NotifyMotionArgs args =
5554 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5555 ADISPLAY_ID_DEFAULT, points);
5556 mDispatcher->notifyMotion(&args);
5557 }
5558};
5559
5560TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005561 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005562 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005563 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005564
5565 touch();
5566
5567 mTouchWindow->assertNoEvents();
5568}
5569
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005570TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00005571 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
5572 const sp<FakeWindowHandle>& w =
5573 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
5574 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5575
5576 touch();
5577
5578 mTouchWindow->assertNoEvents();
5579}
5580
5581TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005582 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
5583 const sp<FakeWindowHandle>& w =
5584 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5585 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5586
5587 touch();
5588
5589 w->assertNoEvents();
5590}
5591
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005592TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005593 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
5594 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005595
5596 touch();
5597
5598 mTouchWindow->consumeAnyMotionDown();
5599}
5600
5601TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005602 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005603 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005604 w->setFrame(Rect(0, 0, 50, 50));
5605 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005606
5607 touch({PointF{100, 100}});
5608
5609 mTouchWindow->consumeAnyMotionDown();
5610}
5611
5612TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005613 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005614 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005615 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5616
5617 touch();
5618
5619 mTouchWindow->consumeAnyMotionDown();
5620}
5621
5622TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
5623 const sp<FakeWindowHandle>& w =
5624 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5625 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005626
5627 touch();
5628
5629 mTouchWindow->consumeAnyMotionDown();
5630}
5631
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005632TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
5633 const sp<FakeWindowHandle>& w =
5634 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
5635 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5636
5637 touch();
5638
5639 w->assertNoEvents();
5640}
5641
5642/**
5643 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
5644 * inside) while letting them pass-through. Note that even though touch passes through the occluding
5645 * window, the occluding window will still receive ACTION_OUTSIDE event.
5646 */
5647TEST_F(InputDispatcherUntrustedTouchesTest,
5648 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
5649 const sp<FakeWindowHandle>& w =
5650 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005651 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005652 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5653
5654 touch();
5655
5656 w->consumeMotionOutside();
5657}
5658
5659TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
5660 const sp<FakeWindowHandle>& w =
5661 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005662 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005663 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5664
5665 touch();
5666
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08005667 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00005668}
5669
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005670TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005671 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005672 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5673 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5675
5676 touch();
5677
5678 mTouchWindow->consumeAnyMotionDown();
5679}
5680
5681TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
5682 const sp<FakeWindowHandle>& w =
5683 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5684 MAXIMUM_OBSCURING_OPACITY);
5685 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005686
5687 touch();
5688
5689 mTouchWindow->consumeAnyMotionDown();
5690}
5691
5692TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005693 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005694 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5695 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005696 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5697
5698 touch();
5699
5700 mTouchWindow->assertNoEvents();
5701}
5702
5703TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
5704 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
5705 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005706 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5707 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005708 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005709 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5710 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5712
5713 touch();
5714
5715 mTouchWindow->assertNoEvents();
5716}
5717
5718TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
5719 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
5720 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005721 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
5722 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005723 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005724 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
5725 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5727
5728 touch();
5729
5730 mTouchWindow->consumeAnyMotionDown();
5731}
5732
5733TEST_F(InputDispatcherUntrustedTouchesTest,
5734 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
5735 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005736 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5737 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005738 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005739 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5740 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005741 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5742
5743 touch();
5744
5745 mTouchWindow->consumeAnyMotionDown();
5746}
5747
5748TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
5749 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005750 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5751 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005752 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005753 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5754 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00005755 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00005756
5757 touch();
5758
5759 mTouchWindow->assertNoEvents();
5760}
5761
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005762TEST_F(InputDispatcherUntrustedTouchesTest,
5763 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
5764 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005765 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5766 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005767 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005768 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5769 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5771
5772 touch();
5773
5774 mTouchWindow->assertNoEvents();
5775}
5776
5777TEST_F(InputDispatcherUntrustedTouchesTest,
5778 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
5779 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005780 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5781 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005782 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005783 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5784 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005785 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
5786
5787 touch();
5788
5789 mTouchWindow->consumeAnyMotionDown();
5790}
5791
5792TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
5793 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005794 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
5795 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00005796 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5797
5798 touch();
5799
5800 mTouchWindow->consumeAnyMotionDown();
5801}
5802
5803TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
5804 const sp<FakeWindowHandle>& w =
5805 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
5806 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5807
5808 touch();
5809
5810 mTouchWindow->consumeAnyMotionDown();
5811}
5812
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005813TEST_F(InputDispatcherUntrustedTouchesTest,
5814 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
5815 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5816 const sp<FakeWindowHandle>& w =
5817 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
5818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5819
5820 touch();
5821
5822 mTouchWindow->assertNoEvents();
5823}
5824
5825TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
5826 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
5827 const sp<FakeWindowHandle>& w =
5828 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
5829 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5830
5831 touch();
5832
5833 mTouchWindow->consumeAnyMotionDown();
5834}
5835
5836TEST_F(InputDispatcherUntrustedTouchesTest,
5837 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
5838 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
5839 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00005840 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5841 OPACITY_ABOVE_THRESHOLD);
5842 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5843
5844 touch();
5845
5846 mTouchWindow->consumeAnyMotionDown();
5847}
5848
5849TEST_F(InputDispatcherUntrustedTouchesTest,
5850 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
5851 const sp<FakeWindowHandle>& w1 =
5852 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5853 OPACITY_BELOW_THRESHOLD);
5854 const sp<FakeWindowHandle>& w2 =
5855 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
5856 OPACITY_BELOW_THRESHOLD);
5857 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
5858
5859 touch();
5860
5861 mTouchWindow->assertNoEvents();
5862}
5863
5864/**
5865 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
5866 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
5867 * (which alone would result in allowing touches) does not affect the blocking behavior.
5868 */
5869TEST_F(InputDispatcherUntrustedTouchesTest,
5870 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
5871 const sp<FakeWindowHandle>& wB =
5872 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
5873 OPACITY_BELOW_THRESHOLD);
5874 const sp<FakeWindowHandle>& wC =
5875 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
5876 OPACITY_BELOW_THRESHOLD);
5877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
5878
5879 touch();
5880
5881 mTouchWindow->assertNoEvents();
5882}
5883
5884/**
5885 * This test is testing that a window from a different UID but with same application token doesn't
5886 * block the touch. Apps can share the application token for close UI collaboration for example.
5887 */
5888TEST_F(InputDispatcherUntrustedTouchesTest,
5889 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
5890 const sp<FakeWindowHandle>& w =
5891 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
5892 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00005893 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
5894
5895 touch();
5896
5897 mTouchWindow->consumeAnyMotionDown();
5898}
5899
arthurhungb89ccb02020-12-30 16:19:01 +08005900class InputDispatcherDragTests : public InputDispatcherTest {
5901protected:
5902 std::shared_ptr<FakeApplicationHandle> mApp;
5903 sp<FakeWindowHandle> mWindow;
5904 sp<FakeWindowHandle> mSecondWindow;
5905 sp<FakeWindowHandle> mDragWindow;
5906
5907 void SetUp() override {
5908 InputDispatcherTest::SetUp();
5909 mApp = std::make_shared<FakeApplicationHandle>();
5910 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
5911 mWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005912 mWindow->setTouchModal(false);
arthurhungb89ccb02020-12-30 16:19:01 +08005913
5914 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
5915 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005916 mSecondWindow->setTouchModal(false);
arthurhungb89ccb02020-12-30 16:19:01 +08005917
5918 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
5919 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
5920 }
5921
5922 // Start performing drag, we will create a drag window and transfer touch to it.
5923 void performDrag() {
5924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5925 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5926 {50, 50}))
5927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5928
5929 // Window should receive motion event.
5930 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5931
5932 // The drag window covers the entire display
5933 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5934 mDispatcher->setInputWindows(
5935 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5936
5937 // Transfer touch focus to the drag window
5938 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5939 true /* isDragDrop */);
5940 mWindow->consumeMotionCancel();
5941 mDragWindow->consumeMotionDown();
5942 }
arthurhung6d4bed92021-03-17 11:59:33 +08005943
5944 // Start performing drag, we will create a drag window and transfer touch to it.
5945 void performStylusDrag() {
5946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5947 injectMotionEvent(mDispatcher,
5948 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
5949 AINPUT_SOURCE_STYLUS)
5950 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
5951 .pointer(PointerBuilder(0,
5952 AMOTION_EVENT_TOOL_TYPE_STYLUS)
5953 .x(50)
5954 .y(50))
5955 .build()));
5956 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5957
5958 // The drag window covers the entire display
5959 mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
5960 mDispatcher->setInputWindows(
5961 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
5962
5963 // Transfer touch focus to the drag window
5964 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
5965 true /* isDragDrop */);
5966 mWindow->consumeMotionCancel();
5967 mDragWindow->consumeMotionDown();
5968 }
arthurhungb89ccb02020-12-30 16:19:01 +08005969};
5970
5971TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
5972 performDrag();
5973
5974 // Move on window.
5975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5976 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5977 ADISPLAY_ID_DEFAULT, {50, 50}))
5978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5979 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5980 mWindow->consumeDragEvent(false, 50, 50);
5981 mSecondWindow->assertNoEvents();
5982
5983 // Move to another window.
5984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5985 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5986 ADISPLAY_ID_DEFAULT, {150, 50}))
5987 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5988 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5989 mWindow->consumeDragEvent(true, 150, 50);
5990 mSecondWindow->consumeDragEvent(false, 50, 50);
5991
5992 // Move back to original window.
5993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5994 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5995 ADISPLAY_ID_DEFAULT, {50, 50}))
5996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5997 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
5998 mWindow->consumeDragEvent(false, 50, 50);
5999 mSecondWindow->consumeDragEvent(true, -50, 50);
6000
6001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6002 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
6003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6004 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6005 mWindow->assertNoEvents();
6006 mSecondWindow->assertNoEvents();
6007}
6008
arthurhungf452d0b2021-01-06 00:19:52 +08006009TEST_F(InputDispatcherDragTests, DragAndDrop) {
6010 performDrag();
6011
6012 // Move on window.
6013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6014 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6015 ADISPLAY_ID_DEFAULT, {50, 50}))
6016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6017 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6018 mWindow->consumeDragEvent(false, 50, 50);
6019 mSecondWindow->assertNoEvents();
6020
6021 // Move to another window.
6022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6023 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6024 ADISPLAY_ID_DEFAULT, {150, 50}))
6025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6026 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6027 mWindow->consumeDragEvent(true, 150, 50);
6028 mSecondWindow->consumeDragEvent(false, 50, 50);
6029
6030 // drop to another window.
6031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6032 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6033 {150, 50}))
6034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6035 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6036 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6037 mWindow->assertNoEvents();
6038 mSecondWindow->assertNoEvents();
6039}
6040
arthurhung6d4bed92021-03-17 11:59:33 +08006041TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
6042 performStylusDrag();
6043
6044 // Move on window and keep button pressed.
6045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6046 injectMotionEvent(mDispatcher,
6047 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
6048 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
6049 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6050 .x(50)
6051 .y(50))
6052 .build()))
6053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6054 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6055 mWindow->consumeDragEvent(false, 50, 50);
6056 mSecondWindow->assertNoEvents();
6057
6058 // Move to another window and release button, expect to drop item.
6059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6060 injectMotionEvent(mDispatcher,
6061 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
6062 .buttonState(0)
6063 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6064 .x(150)
6065 .y(50))
6066 .build()))
6067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6068 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6069 mWindow->assertNoEvents();
6070 mSecondWindow->assertNoEvents();
6071 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6072
6073 // nothing to the window.
6074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6075 injectMotionEvent(mDispatcher,
6076 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
6077 .buttonState(0)
6078 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6079 .x(150)
6080 .y(50))
6081 .build()))
6082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6083 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6084 mWindow->assertNoEvents();
6085 mSecondWindow->assertNoEvents();
6086}
6087
Arthur Hung6d0571e2021-04-09 20:18:16 +08006088TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
6089 performDrag();
6090
6091 // Set second window invisible.
6092 mSecondWindow->setVisible(false);
6093 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
6094
6095 // Move on window.
6096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6097 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6098 ADISPLAY_ID_DEFAULT, {50, 50}))
6099 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6100 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6101 mWindow->consumeDragEvent(false, 50, 50);
6102 mSecondWindow->assertNoEvents();
6103
6104 // Move to another window.
6105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6106 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6107 ADISPLAY_ID_DEFAULT, {150, 50}))
6108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6109 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6110 mWindow->consumeDragEvent(true, 150, 50);
6111 mSecondWindow->assertNoEvents();
6112
6113 // drop to another window.
6114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6115 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6116 {150, 50}))
6117 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6118 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6119 mFakePolicy->assertDropTargetEquals(nullptr);
6120 mWindow->assertNoEvents();
6121 mSecondWindow->assertNoEvents();
6122}
6123
Vishnu Nair062a8672021-09-03 16:07:44 -07006124class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
6125
6126TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
6127 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6128 sp<FakeWindowHandle> window =
6129 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
6130 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT);
6131 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6132 window->setFocusable(true);
6133 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
6134 setFocusedWindow(window);
6135 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6136
6137 // With the flag set, window should not get any input
6138 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
6139 mDispatcher->notifyKey(&keyArgs);
6140 window->assertNoEvents();
6141
6142 NotifyMotionArgs motionArgs =
6143 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6144 ADISPLAY_ID_DEFAULT);
6145 mDispatcher->notifyMotion(&motionArgs);
6146 window->assertNoEvents();
6147
6148 // With the flag cleared, the window should get input
6149 window->setInputFeatures({});
6150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
6151
6152 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
6153 mDispatcher->notifyKey(&keyArgs);
6154 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
6155
6156 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6157 ADISPLAY_ID_DEFAULT);
6158 mDispatcher->notifyMotion(&motionArgs);
6159 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6160 window->assertNoEvents();
6161}
6162
6163TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
6164 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
6165 std::make_shared<FakeApplicationHandle>();
6166 sp<FakeWindowHandle> obscuringWindow =
6167 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
6168 ADISPLAY_ID_DEFAULT);
6169 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
6170 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006171 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07006172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6173 sp<FakeWindowHandle> window =
6174 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
6175 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
6176 window->setOwnerInfo(222, 222);
6177 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6178 window->setFocusable(true);
6179 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
6180 setFocusedWindow(window);
6181 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6182
6183 // With the flag set, window should not get any input
6184 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
6185 mDispatcher->notifyKey(&keyArgs);
6186 window->assertNoEvents();
6187
6188 NotifyMotionArgs motionArgs =
6189 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6190 ADISPLAY_ID_DEFAULT);
6191 mDispatcher->notifyMotion(&motionArgs);
6192 window->assertNoEvents();
6193
6194 // With the flag cleared, the window should get input
6195 window->setInputFeatures({});
6196 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
6197
6198 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
6199 mDispatcher->notifyKey(&keyArgs);
6200 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
6201
6202 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6203 ADISPLAY_ID_DEFAULT);
6204 mDispatcher->notifyMotion(&motionArgs);
6205 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6206 window->assertNoEvents();
6207}
6208
6209TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
6210 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
6211 std::make_shared<FakeApplicationHandle>();
6212 sp<FakeWindowHandle> obscuringWindow =
6213 new FakeWindowHandle(obscuringApplication, mDispatcher, "obscuringWindow",
6214 ADISPLAY_ID_DEFAULT);
6215 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
6216 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006217 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07006218 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6219 sp<FakeWindowHandle> window =
6220 new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
6221 window->setInputFeatures(WindowInfo::Feature::DROP_INPUT_IF_OBSCURED);
6222 window->setOwnerInfo(222, 222);
6223 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6224 window->setFocusable(true);
6225 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
6226 setFocusedWindow(window);
6227 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6228
6229 // With the flag set, window should not get any input
6230 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
6231 mDispatcher->notifyKey(&keyArgs);
6232 window->assertNoEvents();
6233
6234 NotifyMotionArgs motionArgs =
6235 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6236 ADISPLAY_ID_DEFAULT);
6237 mDispatcher->notifyMotion(&motionArgs);
6238 window->assertNoEvents();
6239
6240 // When the window is no longer obscured because it went on top, it should get input
6241 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
6242
6243 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
6244 mDispatcher->notifyKey(&keyArgs);
6245 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
6246
6247 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6248 ADISPLAY_ID_DEFAULT);
6249 mDispatcher->notifyMotion(&motionArgs);
6250 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6251 window->assertNoEvents();
6252}
6253
Antonio Kantekf16f2832021-09-28 04:39:20 +00006254class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
6255protected:
6256 std::shared_ptr<FakeApplicationHandle> mApp;
6257 sp<FakeWindowHandle> mWindow;
6258 sp<FakeWindowHandle> mSecondWindow;
6259
6260 void SetUp() override {
6261 InputDispatcherTest::SetUp();
6262
6263 mApp = std::make_shared<FakeApplicationHandle>();
6264 mWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
6265 mWindow->setFocusable(true);
6266 mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
6267 mSecondWindow->setFocusable(true);
6268
6269 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
6270 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
6271
6272 setFocusedWindow(mWindow);
6273 mWindow->consumeFocusEvent(true);
6274 }
6275
Antonio Kantekea47acb2021-12-23 12:41:25 -08006276 void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) {
6277 mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006278 mWindow->consumeTouchModeEvent(inTouchMode);
6279 mSecondWindow->consumeTouchModeEvent(inTouchMode);
6280 }
6281};
6282
6283TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchModeOnFocusedWindow) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08006284 const WindowInfo& windowInfo = *mWindow->getInfo();
6285 changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid,
6286 windowInfo.ownerUid, /* hasPermission */ false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006287}
6288
6289TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08006290 const WindowInfo& windowInfo = *mWindow->getInfo();
6291 mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid,
6292 windowInfo.ownerUid, /* hasPermission */ true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006293 mWindow->assertNoEvents();
6294 mSecondWindow->assertNoEvents();
6295}
6296
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006297class InputDispatcherSpyWindowTest : public InputDispatcherTest {
6298public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006299 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006300 std::shared_ptr<FakeApplicationHandle> application =
6301 std::make_shared<FakeApplicationHandle>();
6302 std::string name = "Fake Spy ";
6303 name += std::to_string(mSpyCount++);
6304 sp<FakeWindowHandle> spy =
6305 new FakeWindowHandle(application, mDispatcher, name.c_str(), ADISPLAY_ID_DEFAULT);
6306 spy->setInputFeatures(WindowInfo::Feature::SPY);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08006307 spy->setTrustedOverlay(true);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006308 spy->setTouchModal(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006309 return spy;
6310 }
6311
6312 sp<FakeWindowHandle> createForeground() {
6313 std::shared_ptr<FakeApplicationHandle> application =
6314 std::make_shared<FakeApplicationHandle>();
6315 sp<FakeWindowHandle> window =
6316 new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006317 window->setFocusable(true);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006318 window->setTouchModal(false);
6319 window->setSplitTouch(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006320 return window;
6321 }
6322
6323private:
6324 int mSpyCount{0};
6325};
6326
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08006327using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006328/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08006329 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
6330 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08006331TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
6332 ScopedSilentDeath _silentDeath;
6333
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006334 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08006335 spy->setTrustedOverlay(false);
6336 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
6337 ".* not a trusted overlay");
6338}
6339
6340/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006341 * Input injection into a display with a spy window but no foreground windows should succeed.
6342 */
6343TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006344 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006345 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
6346
6347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6348 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6349 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6350 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6351}
6352
6353/**
6354 * Verify the order in which different input windows receive events. The touched foreground window
6355 * (if there is one) should always receive the event first. When there are multiple spy windows, the
6356 * spy windows will receive the event according to their Z-order, where the top-most spy window will
6357 * receive events before ones belows it.
6358 *
6359 * Here, we set up a scenario with four windows in the following Z order from the top:
6360 * spy1, spy2, window, spy3.
6361 * We then inject an event and verify that the foreground "window" receives it first, followed by
6362 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
6363 * window.
6364 */
6365TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
6366 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006367 auto spy1 = createSpy();
6368 auto spy2 = createSpy();
6369 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006370 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
6371 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
6372 const size_t numChannels = channels.size();
6373
6374 base::unique_fd epollFd(epoll_create1(0 /*flags*/));
6375 if (!epollFd.ok()) {
6376 FAIL() << "Failed to create epoll fd";
6377 }
6378
6379 for (size_t i = 0; i < numChannels; i++) {
6380 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
6381 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
6382 FAIL() << "Failed to add fd to epoll";
6383 }
6384 }
6385
6386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6387 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6388 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6389
6390 std::vector<size_t> eventOrder;
6391 std::vector<struct epoll_event> events(numChannels);
6392 for (;;) {
6393 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
6394 (100ms).count());
6395 if (nFds < 0) {
6396 FAIL() << "Failed to call epoll_wait";
6397 }
6398 if (nFds == 0) {
6399 break; // epoll_wait timed out
6400 }
6401 for (int i = 0; i < nFds; i++) {
6402 ASSERT_EQ(EPOLLIN, events[i].events);
6403 eventOrder.push_back(events[i].data.u64);
6404 channels[i]->consumeMotionDown();
6405 }
6406 }
6407
6408 // Verify the order in which the events were received.
6409 EXPECT_EQ(3u, eventOrder.size());
6410 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
6411 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
6412 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
6413}
6414
6415/**
6416 * A spy window using the NOT_TOUCHABLE flag does not receive events.
6417 */
6418TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
6419 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006420 auto spy = createSpy();
6421 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006422 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6423
6424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6425 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6427 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6428 spy->assertNoEvents();
6429}
6430
6431/**
6432 * A spy window will only receive gestures that originate within its touchable region. Gestures that
6433 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
6434 * to the window.
6435 */
6436TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
6437 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006438 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006439 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
6440 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6441
6442 // Inject an event outside the spy window's touchable region.
6443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6444 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6445 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6446 window->consumeMotionDown();
6447 spy->assertNoEvents();
6448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6449 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6450 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6451 window->consumeMotionUp();
6452 spy->assertNoEvents();
6453
6454 // Inject an event inside the spy window's touchable region.
6455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6456 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6457 {5, 10}))
6458 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6459 window->consumeMotionDown();
6460 spy->consumeMotionDown();
6461}
6462
6463/**
6464 * A spy window that is a modal window will receive gestures outside of its frame and touchable
6465 * region.
6466 */
6467TEST_F(InputDispatcherSpyWindowTest, ModalWindow) {
6468 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006469 auto spy = createSpy();
6470 // Our current policy dictates that modal windows must be focusable.
6471 spy->setFocusable(true);
6472 spy->setTouchModal(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006473 spy->setFrame(Rect{0, 0, 20, 20});
6474 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6475
6476 // Inject an event outside the spy window's frame and touchable region.
6477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6478 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6479 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6480 window->consumeMotionDown();
6481 spy->consumeMotionDown();
6482}
6483
6484/**
6485 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006486 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006487 */
6488TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
6489 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006490 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006491 auto spy = createSpy();
6492 spy->setWatchOutsideTouch(true);
6493 spy->setTouchModal(false);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006494 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006495 spy->setFrame(Rect{0, 0, 20, 20});
6496 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6497
6498 // Inject an event outside the spy window's frame and touchable region.
6499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006500 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6501 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006502 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6503 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006504 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006505}
6506
6507/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006508 * A spy window can pilfer pointers. When this happens, touch gestures that are currently sent to
6509 * any other windows - including other spy windows - will also be cancelled.
6510 */
6511TEST_F(InputDispatcherSpyWindowTest, PilferPointers) {
6512 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006513 auto spy1 = createSpy();
6514 auto spy2 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006515 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
6516
6517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6518 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6519 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6520 window->consumeMotionDown();
6521 spy1->consumeMotionDown();
6522 spy2->consumeMotionDown();
6523
6524 // Pilfer pointers from the second spy window.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006525 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006526 spy2->assertNoEvents();
6527 spy1->consumeMotionCancel();
6528 window->consumeMotionCancel();
6529
6530 // The rest of the gesture should only be sent to the second spy window.
6531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6532 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6533 ADISPLAY_ID_DEFAULT))
6534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6535 spy2->consumeMotionMove();
6536 spy1->assertNoEvents();
6537 window->assertNoEvents();
6538}
6539
6540/**
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006541 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
6542 * in the middle of the gesture.
6543 */
6544TEST_F(InputDispatcherSpyWindowTest, CanPilferAfterWindowIsRemovedMidStream) {
6545 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006546 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006547 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6548
6549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6550 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6551 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6552 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6553 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6554
6555 window->releaseChannel();
6556
6557 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
6558
6559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6560 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6562 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6563}
6564
6565/**
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006566 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
6567 * the spy, but not to any other windows.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006568 */
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006569TEST_F(InputDispatcherSpyWindowTest, ContinuesToReceiveGestureAfterPilfer) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006570 auto spy = createSpy();
6571 spy->setTouchModal(false);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006572 auto window = createForeground();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006573
6574 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6575
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006576 // First finger down on the window and the spy.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6578 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6579 {100, 200}))
6580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006581 spy->consumeMotionDown();
6582 window->consumeMotionDown();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006583
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006584 // Spy window pilfers the pointers.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006585 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006586 window->consumeMotionCancel();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006587
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006588 // Second finger down on the window and spy, but the window should not receive the pointer down.
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006589 const MotionEvent secondFingerDownEvent =
6590 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6591 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6592 AINPUT_SOURCE_TOUCHSCREEN)
6593 .displayId(ADISPLAY_ID_DEFAULT)
6594 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6595 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
6596 .x(100)
6597 .y(200))
6598 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6599 .build();
6600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6601 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6602 InputEventInjectionSync::WAIT_FOR_RESULT))
6603 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6604
Prabir Pradhane680f9b2022-02-04 04:24:00 -08006605 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
6606
6607 // Third finger goes down outside all windows, so injection should fail.
6608 const MotionEvent thirdFingerDownEvent =
6609 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6610 (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6611 AINPUT_SOURCE_TOUCHSCREEN)
6612 .displayId(ADISPLAY_ID_DEFAULT)
6613 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6614 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
6615 .x(100)
6616 .y(200))
6617 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6618 .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
6619 .build();
6620 ASSERT_EQ(InputEventInjectionResult::FAILED,
6621 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
6622 InputEventInjectionSync::WAIT_FOR_RESULT))
6623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6624
6625 spy->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006626 window->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006627}
6628
6629/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006630 * Even when a spy window spans over multiple foreground windows, the spy should receive all
6631 * pointers that are down within its bounds.
6632 */
6633TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
6634 auto windowLeft = createForeground();
6635 windowLeft->setFrame({0, 0, 100, 200});
6636 auto windowRight = createForeground();
6637 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006638 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006639 spy->setFrame({0, 0, 200, 200});
6640 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
6641
6642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6643 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6644 {50, 50}))
6645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6646 windowLeft->consumeMotionDown();
6647 spy->consumeMotionDown();
6648
6649 const MotionEvent secondFingerDownEvent =
6650 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6651 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6652 AINPUT_SOURCE_TOUCHSCREEN)
6653 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6654 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6655 .pointer(
6656 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6657 .build();
6658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6659 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6660 InputEventInjectionSync::WAIT_FOR_RESULT))
6661 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6662 windowRight->consumeMotionDown();
6663 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
6664}
6665
6666/**
6667 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
6668 * the spy should receive the second pointer with ACTION_DOWN.
6669 */
6670TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
6671 auto window = createForeground();
6672 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006673 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08006674 spyRight->setFrame({100, 0, 200, 200});
6675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
6676
6677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6678 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6679 {50, 50}))
6680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6681 window->consumeMotionDown();
6682 spyRight->assertNoEvents();
6683
6684 const MotionEvent secondFingerDownEvent =
6685 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6686 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6687 AINPUT_SOURCE_TOUCHSCREEN)
6688 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6689 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6690 .pointer(
6691 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
6692 .build();
6693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6694 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6695 InputEventInjectionSync::WAIT_FOR_RESULT))
6696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6697 window->consumeMotionPointerDown(1 /*pointerIndex*/);
6698 spyRight->consumeMotionDown();
6699}
6700
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006701/**
6702 * The spy window should not be able to affect whether or not touches are split. Only the foreground
6703 * windows should be allowed to control split touch.
6704 */
6705TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
6706 // Create a touch modal spy that spies on the entire display.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006707 // This spy window does not set split touch. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006708 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006709 auto spy = createSpy();
6710 spy->setTouchModal(true);
6711 spy->setSplitTouch(false);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006712
6713 // Create a non touch modal window that supports split touch.
6714 auto window = createForeground();
6715 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006716
6717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6718
6719 // First finger down, no window touched.
6720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6721 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6722 {100, 200}))
6723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6724 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6725 window->assertNoEvents();
6726
6727 // Second finger down on window, the window should receive touch down.
6728 const MotionEvent secondFingerDownEvent =
6729 MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
6730 (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
6731 AINPUT_SOURCE_TOUCHSCREEN)
6732 .displayId(ADISPLAY_ID_DEFAULT)
6733 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6734 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
6735 .x(100)
6736 .y(200))
6737 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6738 .build();
6739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6740 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6741 InputEventInjectionSync::WAIT_FOR_RESULT))
6742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6743
6744 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6745 spy->consumeMotionPointerDown(1 /* pointerIndex */);
6746}
6747
6748/**
6749 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
6750 * do not receive key events.
6751 */
6752TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006753 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006754 spy->setFocusable(false);
6755
6756 auto window = createForeground();
6757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
6758 setFocusedWindow(window);
6759 window->consumeFocusEvent(true);
6760
6761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6762 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
6763 window->consumeKeyDown(ADISPLAY_ID_NONE);
6764
6765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
6766 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
6767 window->consumeKeyUp(ADISPLAY_ID_NONE);
6768
6769 spy->assertNoEvents();
6770}
6771
Prabir Pradhand65552b2021-10-07 11:23:50 -07006772class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
6773public:
6774 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
6775 std::shared_ptr<FakeApplicationHandle> overlayApplication =
6776 std::make_shared<FakeApplicationHandle>();
6777 sp<FakeWindowHandle> overlay =
6778 new FakeWindowHandle(overlayApplication, mDispatcher, "Stylus interceptor window",
6779 ADISPLAY_ID_DEFAULT);
6780 overlay->setFocusable(false);
6781 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006782 overlay->setTouchable(false);
6783 overlay->setSplitTouch(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07006784 overlay->setInputFeatures(WindowInfo::Feature::INTERCEPTS_STYLUS);
6785 overlay->setTrustedOverlay(true);
6786
6787 std::shared_ptr<FakeApplicationHandle> application =
6788 std::make_shared<FakeApplicationHandle>();
6789 sp<FakeWindowHandle> window =
6790 new FakeWindowHandle(application, mDispatcher, "Application window",
6791 ADISPLAY_ID_DEFAULT);
6792 window->setFocusable(true);
6793 window->setOwnerInfo(222, 222);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006794 window->setSplitTouch(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07006795
6796 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6797 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
6798 setFocusedWindow(window);
6799 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
6800 return {std::move(overlay), std::move(window)};
6801 }
6802
6803 void sendFingerEvent(int32_t action) {
6804 NotifyMotionArgs motionArgs =
6805 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
6806 ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
6807 mDispatcher->notifyMotion(&motionArgs);
6808 }
6809
6810 void sendStylusEvent(int32_t action) {
6811 NotifyMotionArgs motionArgs =
6812 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
6813 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
6814 motionArgs.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
6815 mDispatcher->notifyMotion(&motionArgs);
6816 }
6817};
6818
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08006819using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
6820
6821TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
6822 ScopedSilentDeath _silentDeath;
6823
Prabir Pradhand65552b2021-10-07 11:23:50 -07006824 auto [overlay, window] = setupStylusOverlayScenario();
6825 overlay->setTrustedOverlay(false);
6826 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
6827 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
6828 ".* not a trusted overlay");
6829}
6830
6831TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
6832 auto [overlay, window] = setupStylusOverlayScenario();
6833 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
6834
6835 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
6836 overlay->consumeMotionDown();
6837 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
6838 overlay->consumeMotionUp();
6839
6840 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
6841 window->consumeMotionDown();
6842 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
6843 window->consumeMotionUp();
6844
6845 overlay->assertNoEvents();
6846 window->assertNoEvents();
6847}
6848
6849TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
6850 auto [overlay, window] = setupStylusOverlayScenario();
6851 overlay->setInputFeatures(overlay->getInfo()->inputFeatures | WindowInfo::Feature::SPY);
6852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
6853
6854 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
6855 overlay->consumeMotionDown();
6856 window->consumeMotionDown();
6857 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
6858 overlay->consumeMotionUp();
6859 window->consumeMotionUp();
6860
6861 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
6862 window->consumeMotionDown();
6863 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
6864 window->consumeMotionUp();
6865
6866 overlay->assertNoEvents();
6867 window->assertNoEvents();
6868}
6869
Antonio Kantekea47acb2021-12-23 12:41:25 -08006870// TODO(b/198487159): Add permission tests for touch mode switch once the validation is put in
6871// place.
6872
Garfield Tane84e6f92019-08-29 17:28:41 -07006873} // namespace android::inputdispatcher