blob: c04227d16c2b6586950036fb988d4004ac8952da [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070019#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080020#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080021#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070022#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070023#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000024#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080025#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080026#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100027#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080029#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080032#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070033#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080034#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080035#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036
Garfield Tan1c7bc862020-01-28 13:24:04 -080037using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050038using android::gui::FocusRequest;
39using android::gui::TouchOcclusionMode;
40using android::gui::WindowInfo;
41using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080042using android::os::InputEventInjectionResult;
43using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080044
Garfield Tane84e6f92019-08-29 17:28:41 -070045namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080046
Dominik Laskowski2f01d772022-03-23 16:01:29 -070047using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080048using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049
Michael Wrightd02c5b62014-02-10 15:10:22 -080050// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000051static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
53// An arbitrary device id.
Prabir Pradhan5735a322022-04-11 17:23:34 +000054static constexpr int32_t DEVICE_ID = 1;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080055static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080056
Jeff Brownf086ddb2014-02-11 14:28:48 -080057// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000058static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
59static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080060
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080061static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080062static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080063static constexpr int32_t POINTER_1_DOWN =
64 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000065static constexpr int32_t POINTER_2_DOWN =
66 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000067static constexpr int32_t POINTER_3_DOWN =
68 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000069static constexpr int32_t POINTER_0_UP =
70 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080071static constexpr int32_t POINTER_1_UP =
72 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
73
Antonio Kantek15beb512022-06-13 22:35:41 +000074// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000075static constexpr int32_t WINDOW_PID = 999;
76static constexpr int32_t WINDOW_UID = 1001;
77
Antonio Kantek15beb512022-06-13 22:35:41 +000078// The default pid and uid for the windows created on the secondary display by the test.
79static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
80static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
81
Prabir Pradhan5735a322022-04-11 17:23:34 +000082// The default policy flags to use for event injection by tests.
83static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
Michael Wrightd02c5b62014-02-10 15:10:22 -080084
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +000085// An arbitrary pid of the gesture monitor window
86static constexpr int32_t MONITOR_PID = 2001;
87
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080088static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
89
Arthur Hungc539dbb2022-12-08 07:45:36 +000090static constexpr int expectedWallpaperFlags =
91 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
92
chaviwd1c23182019-12-20 18:44:56 -080093struct PointF {
94 float x;
95 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080096 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -080097};
Michael Wrightd02c5b62014-02-10 15:10:22 -080098
Gang Wang342c9272020-01-13 13:15:04 -050099/**
100 * Return a DOWN key event with KEYCODE_A.
101 */
102static KeyEvent getTestKeyEvent() {
103 KeyEvent event;
104
Garfield Tanfbe732e2020-01-24 11:26:14 -0800105 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
106 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
107 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500108 return event;
109}
110
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000111static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
112 ASSERT_EQ(expectedAction, receivedAction)
113 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
114 << MotionEvent::actionToString(receivedAction);
115}
116
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800117MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
118 bool matches = action == arg.getAction();
119 if (!matches) {
120 *result_listener << "expected action " << MotionEvent::actionToString(action)
121 << ", but got " << MotionEvent::actionToString(arg.getAction());
122 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800123 if (action == AMOTION_EVENT_ACTION_DOWN) {
124 if (!matches) {
125 *result_listener << "; ";
126 }
127 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
128 matches &= arg.getDownTime() == arg.getEventTime();
129 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800130 if (action == AMOTION_EVENT_ACTION_CANCEL) {
131 if (!matches) {
132 *result_listener << "; ";
133 }
134 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
135 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
136 }
137 return matches;
138}
139
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800140MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
141 return arg.getDownTime() == downTime;
142}
143
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800144MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
145 return arg.getDisplayId() == displayId;
146}
147
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800148MATCHER_P(WithSource, source, "InputEvent with specified source") {
149 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
150 << inputEventSourceToString(arg.getSource());
151 return arg.getSource() == source;
152}
153
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800154MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
155 return arg.getFlags() == flags;
156}
157
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800158MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
159 if (arg.getPointerCount() != 1) {
160 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
161 return false;
162 }
163 return arg.getX(0 /*pointerIndex*/) == x && arg.getY(0 /*pointerIndex*/) == y;
164}
165
166MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
167 // Build a map for the received pointers, by pointer id
168 std::map<int32_t /*pointerId*/, PointF> actualPointers;
169 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
170 const int32_t pointerId = arg.getPointerId(pointerIndex);
171 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
172 }
173 return pointers == actualPointers;
174}
175
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176// --- FakeInputDispatcherPolicy ---
177
178class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
179 InputDispatcherConfiguration mConfig;
180
Prabir Pradhanedd96402022-02-15 01:46:16 -0800181 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
182
Michael Wrightd02c5b62014-02-10 15:10:22 -0800183protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000184 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800185
186public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000187 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +0800188
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800189 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700190 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
191 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
192 EXPECT_EQ(event.getDisplayId(), args.displayId);
193
194 const auto& keyEvent = static_cast<const KeyEvent&>(event);
195 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
196 EXPECT_EQ(keyEvent.getAction(), args.action);
197 });
Jackal Guof9696682018-10-05 12:23:23 +0800198 }
199
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700200 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
201 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
202 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
203 EXPECT_EQ(event.getDisplayId(), args.displayId);
204
205 const auto& motionEvent = static_cast<const MotionEvent&>(event);
206 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
207 EXPECT_EQ(motionEvent.getAction(), args.action);
208 EXPECT_EQ(motionEvent.getX(0), point.x);
209 EXPECT_EQ(motionEvent.getY(0), point.y);
210 EXPECT_EQ(motionEvent.getRawX(0), point.x);
211 EXPECT_EQ(motionEvent.getRawY(0), point.y);
212 });
Jackal Guof9696682018-10-05 12:23:23 +0800213 }
214
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700215 void assertFilterInputEventWasNotCalled() {
216 std::scoped_lock lock(mLock);
217 ASSERT_EQ(nullptr, mFilteredEvent);
218 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800219
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800220 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700221 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 ASSERT_TRUE(mConfigurationChangedTime)
223 << "Timed out waiting for configuration changed call";
224 ASSERT_EQ(*mConfigurationChangedTime, when);
225 mConfigurationChangedTime = std::nullopt;
226 }
227
228 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700229 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800230 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800231 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800232 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
233 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
234 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
235 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
236 mLastNotifySwitch = std::nullopt;
237 }
238
chaviwfd6d3512019-03-25 13:23:49 -0700239 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700240 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800241 ASSERT_EQ(touchedToken, mOnPointerDownToken);
242 mOnPointerDownToken.clear();
243 }
244
245 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700246 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800247 ASSERT_TRUE(mOnPointerDownToken == nullptr)
248 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700249 }
250
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700251 // This function must be called soon after the expected ANR timer starts,
252 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500253 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700254 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500255 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800256 std::unique_lock lock(mLock);
257 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500258 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800259 ASSERT_NO_FATAL_FAILURE(
260 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500261 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700262 }
263
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000264 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800265 const sp<WindowInfoHandle>& window) {
266 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
267 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
268 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500269 }
270
Prabir Pradhanedd96402022-02-15 01:46:16 -0800271 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
272 const sp<IBinder>& expectedToken,
273 int32_t expectedPid) {
274 std::unique_lock lock(mLock);
275 android::base::ScopedLockAssertion assumeLocked(mLock);
276 AnrResult result;
277 ASSERT_NO_FATAL_FAILURE(result =
278 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
279 const auto& [token, pid] = result;
280 ASSERT_EQ(expectedToken, token);
281 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500282 }
283
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000285 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500286 std::unique_lock lock(mLock);
287 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800288 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
289 const auto& [token, _] = result;
290 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000291 }
292
Prabir Pradhanedd96402022-02-15 01:46:16 -0800293 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
294 int32_t expectedPid) {
295 std::unique_lock lock(mLock);
296 android::base::ScopedLockAssertion assumeLocked(mLock);
297 AnrResult result;
298 ASSERT_NO_FATAL_FAILURE(
299 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
300 const auto& [token, pid] = result;
301 ASSERT_EQ(expectedToken, token);
302 ASSERT_EQ(expectedPid, pid);
303 }
304
305 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000306 sp<IBinder> getResponsiveWindowToken() {
307 std::unique_lock lock(mLock);
308 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800309 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
310 const auto& [token, _] = result;
311 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700312 }
313
314 void assertNotifyAnrWasNotCalled() {
315 std::scoped_lock lock(mLock);
316 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800317 ASSERT_TRUE(mAnrWindows.empty());
318 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500319 << "ANR was not called, but please also consume the 'connection is responsive' "
320 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700321 }
322
Garfield Tan1c7bc862020-01-28 13:24:04 -0800323 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
324 mConfig.keyRepeatTimeout = timeout;
325 mConfig.keyRepeatDelay = delay;
326 }
327
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000328 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800329 std::unique_lock lock(mLock);
330 base::ScopedLockAssertion assumeLocked(mLock);
331
332 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
333 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000334 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800335 enabled;
336 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000337 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
338 << ") to be called.";
339 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800340 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000341 auto request = *mPointerCaptureRequest;
342 mPointerCaptureRequest.reset();
343 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800344 }
345
346 void assertSetPointerCaptureNotCalled() {
347 std::unique_lock lock(mLock);
348 base::ScopedLockAssertion assumeLocked(mLock);
349
350 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000351 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800352 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000353 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800354 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000355 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800356 }
357
arthurhungf452d0b2021-01-06 00:19:52 +0800358 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
359 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800360 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800361 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800362 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800363 }
364
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800365 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
366 std::unique_lock lock(mLock);
367 base::ScopedLockAssertion assumeLocked(mLock);
368 std::optional<sp<IBinder>> receivedToken =
369 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
370 mNotifyInputChannelBroken);
371 ASSERT_TRUE(receivedToken.has_value());
372 ASSERT_EQ(token, *receivedToken);
373 }
374
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800375 /**
376 * Set policy timeout. A value of zero means next key will not be intercepted.
377 */
378 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
379 mInterceptKeyTimeout = timeout;
380 }
381
Michael Wrightd02c5b62014-02-10 15:10:22 -0800382private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700383 std::mutex mLock;
384 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
385 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
386 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
387 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800388
Prabir Pradhan99987712020-11-10 18:43:05 -0800389 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000390
391 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800392
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700393 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700394 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800395 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
396 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700397 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800398 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
399 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700400
arthurhungf452d0b2021-01-06 00:19:52 +0800401 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800402 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800403
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800404 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
405
Prabir Pradhanedd96402022-02-15 01:46:16 -0800406 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
407 // for a specific container to become non-empty. When the container is non-empty, return the
408 // first entry from the container and erase it.
409 template <class T>
410 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
411 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
412 // If there is an ANR, Dispatcher won't be idle because there are still events
413 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
414 // before checking if ANR was called.
415 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
416 // to provide it some time to act. 100ms seems reasonable.
417 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
418 const std::chrono::time_point start = std::chrono::steady_clock::now();
419 std::optional<T> token =
420 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
421 if (!token.has_value()) {
422 ADD_FAILURE() << "Did not receive the ANR callback";
423 return {};
424 }
425
426 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
427 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
428 // the dispatcher started counting before this function was called
429 if (std::chrono::abs(timeout - waited) > 100ms) {
430 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
431 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
432 << "ms, but waited "
433 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
434 << "ms instead";
435 }
436 return *token;
437 }
438
439 template <class T>
440 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
441 std::queue<T>& storage,
442 std::unique_lock<std::mutex>& lock,
443 std::condition_variable& condition)
444 REQUIRES(mLock) {
445 condition.wait_for(lock, timeout,
446 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
447 if (storage.empty()) {
448 ADD_FAILURE() << "Did not receive the expected callback";
449 return std::nullopt;
450 }
451 T item = storage.front();
452 storage.pop();
453 return std::make_optional(item);
454 }
455
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600456 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700457 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800458 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800459 }
460
Prabir Pradhanedd96402022-02-15 01:46:16 -0800461 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
462 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700463 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800464 ASSERT_TRUE(pid.has_value());
465 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700466 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500467 }
468
Prabir Pradhanedd96402022-02-15 01:46:16 -0800469 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
470 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500471 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800472 ASSERT_TRUE(pid.has_value());
473 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500474 mNotifyAnr.notify_all();
475 }
476
477 void notifyNoFocusedWindowAnr(
478 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
479 std::scoped_lock lock(mLock);
480 mAnrApplications.push(applicationHandle);
481 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800482 }
483
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800484 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
485 std::scoped_lock lock(mLock);
486 mBrokenInputChannels.push(connectionToken);
487 mNotifyInputChannelBroken.notify_all();
488 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800489
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600490 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700491
Chris Yef59a2f42020-10-16 12:55:26 -0700492 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
493 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
494 const std::vector<float>& values) override {}
495
496 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
497 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000498
Chris Yefb552902021-02-03 17:18:37 -0800499 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
500
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600501 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800502 *outConfig = mConfig;
503 }
504
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600505 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700506 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800507 switch (inputEvent->getType()) {
508 case AINPUT_EVENT_TYPE_KEY: {
509 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800510 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800511 break;
512 }
513
514 case AINPUT_EVENT_TYPE_MOTION: {
515 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800516 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800517 break;
518 }
519 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800520 return true;
521 }
522
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800523 void interceptKeyBeforeQueueing(const KeyEvent* inputEvent, uint32_t&) override {
524 if (inputEvent->getAction() == AKEY_EVENT_ACTION_UP) {
525 // Clear intercept state when we handled the event.
526 mInterceptKeyTimeout = 0ms;
527 }
528 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800529
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600530 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800531
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600532 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800533 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
534 // Clear intercept state so we could dispatch the event in next wake.
535 mInterceptKeyTimeout = 0ms;
536 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800537 }
538
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600539 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800540 return false;
541 }
542
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600543 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
544 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700545 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800546 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
547 * essentially a passthrough for notifySwitch.
548 */
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800549 mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800550 }
551
Sean Stoutb4e0a592021-02-23 07:34:53 -0800552 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600554 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700555 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700556 mOnPointerDownToken = newToken;
557 }
558
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000559 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800560 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000561 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800562 mPointerCaptureChangedCondition.notify_all();
563 }
564
arthurhungf452d0b2021-01-06 00:19:52 +0800565 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
566 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800567 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800568 mDropTargetWindowToken = token;
569 }
570
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700571 void assertFilterInputEventWasCalledInternal(
572 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700573 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800574 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700575 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800576 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800577 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800578};
579
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580// --- InputDispatcherTest ---
581
582class InputDispatcherTest : public testing::Test {
583protected:
584 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700585 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000587 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700588 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800589 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800590 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000591 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700592 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593 }
594
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000595 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700596 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800597 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700598 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700600
601 /**
602 * Used for debugging when writing the test
603 */
604 void dumpDispatcherState() {
605 std::string dump;
606 mDispatcher->dump(dump);
607 std::stringstream ss(dump);
608 std::string to;
609
610 while (std::getline(ss, to, '\n')) {
611 ALOGE("%s", to.c_str());
612 }
613 }
Vishnu Nair958da932020-08-21 17:12:37 -0700614
chaviw3277faf2021-05-19 16:45:23 -0500615 void setFocusedWindow(const sp<WindowInfoHandle>& window,
616 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700617 FocusRequest request;
618 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000619 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700620 if (focusedWindow) {
621 request.focusedToken = focusedWindow->getToken();
622 }
623 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
624 request.displayId = window->getInfo()->displayId;
625 mDispatcher->setFocusedWindow(request);
626 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800627};
628
Michael Wrightd02c5b62014-02-10 15:10:22 -0800629TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
630 KeyEvent event;
631
632 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800633 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
634 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600635 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
636 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800637 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000638 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
639 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 << "Should reject key events with undefined action.";
641
642 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800643 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
644 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600645 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800646 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000647 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
648 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800649 << "Should reject key events with ACTION_MULTIPLE.";
650}
651
652TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
653 MotionEvent event;
654 PointerProperties pointerProperties[MAX_POINTERS + 1];
655 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800656 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800657 pointerProperties[i].clear();
658 pointerProperties[i].id = i;
659 pointerCoords[i].clear();
660 }
661
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800662 // Some constants commonly used below
663 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
664 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
665 constexpr int32_t metaState = AMETA_NONE;
666 constexpr MotionClassification classification = MotionClassification::NONE;
667
chaviw9eaa22c2020-07-01 16:21:27 -0700668 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800669 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800670 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700671 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
672 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700673 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
674 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700675 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800676 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000677 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
678 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679 << "Should reject motion events with undefined action.";
680
681 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800682 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800683 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
684 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
685 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
686 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500687 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800688 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000689 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
690 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800691 << "Should reject motion events with pointer down index too large.";
692
Garfield Tanfbe732e2020-01-24 11:26:14 -0800693 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700694 AMOTION_EVENT_ACTION_POINTER_DOWN |
695 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700696 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
697 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700698 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500699 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800700 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000701 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
702 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800703 << "Should reject motion events with pointer down index too small.";
704
705 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800706 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800707 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
708 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
709 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
710 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500711 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800712 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000713 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
714 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800715 << "Should reject motion events with pointer up index too large.";
716
Garfield Tanfbe732e2020-01-24 11:26:14 -0800717 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700718 AMOTION_EVENT_ACTION_POINTER_UP |
719 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700720 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
721 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700722 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500723 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800724 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000725 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
726 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800727 << "Should reject motion events with pointer up index too small.";
728
729 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
731 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700732 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700733 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
734 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700735 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000737 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
738 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800739 << "Should reject motion events with 0 pointers.";
740
Garfield Tanfbe732e2020-01-24 11:26:14 -0800741 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
742 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700743 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700744 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
745 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700746 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800747 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000748 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
749 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800750 << "Should reject motion events with more than MAX_POINTERS pointers.";
751
752 // Rejects motion events with invalid pointer ids.
753 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800754 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
755 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700756 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700757 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
758 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700759 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800760 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000761 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
762 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800763 << "Should reject motion events with pointer ids less than 0.";
764
765 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800766 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
767 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700768 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700769 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
770 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700771 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800772 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000773 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
774 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800775 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
776
777 // Rejects motion events with duplicate pointer ids.
778 pointerProperties[0].id = 1;
779 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800780 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
781 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700782 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700783 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
784 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700785 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000787 mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with duplicate pointer ids.";
790}
791
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800792/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
793
794TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
795 constexpr nsecs_t eventTime = 20;
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800796 NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800797 mDispatcher->notifyConfigurationChanged(&args);
798 ASSERT_TRUE(mDispatcher->waitForIdle());
799
800 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
801}
802
803TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800804 NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
805 2 /*switchMask*/);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800806 mDispatcher->notifySwitch(&args);
807
808 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
809 args.policyFlags |= POLICY_FLAG_TRUSTED;
810 mFakePolicy->assertNotifySwitchWasCalled(args);
811}
812
Arthur Hungb92218b2018-08-14 12:00:21 +0800813// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700814static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700815// Default input dispatching timeout if there is no focused application or paused window
816// from which to determine an appropriate dispatching timeout.
817static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
818 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
819 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800820
821class FakeApplicationHandle : public InputApplicationHandle {
822public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700823 FakeApplicationHandle() {
824 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700825 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500826 mInfo.dispatchingTimeoutMillis =
827 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700828 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800829 virtual ~FakeApplicationHandle() {}
830
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000831 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700832
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500833 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
834 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700835 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800836};
837
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800838class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800839public:
Garfield Tan15601662020-09-22 15:32:38 -0700840 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800841 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700842 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800843 }
844
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800845 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700846 InputEvent* event;
847 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
848 if (!consumeSeq) {
849 return nullptr;
850 }
851 finishEvent(*consumeSeq);
852 return event;
853 }
854
855 /**
856 * Receive an event without acknowledging it.
857 * Return the sequence number that could later be used to send finished signal.
858 */
859 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800860 uint32_t consumeSeq;
861 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800862
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800863 std::chrono::time_point start = std::chrono::steady_clock::now();
864 status_t status = WOULD_BLOCK;
865 while (status == WOULD_BLOCK) {
chaviw81e2bb92019-12-18 15:03:51 -0800866 status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800867 &event);
868 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
869 if (elapsed > 100ms) {
870 break;
871 }
872 }
873
874 if (status == WOULD_BLOCK) {
875 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700876 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800877 }
878
879 if (status != OK) {
880 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800882 }
883 if (event == nullptr) {
884 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800886 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700887 if (outEvent != nullptr) {
888 *outEvent = event;
889 }
890 return consumeSeq;
891 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800892
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700893 /**
894 * To be used together with "receiveEvent" to complete the consumption of an event.
895 */
896 void finishEvent(uint32_t consumeSeq) {
897 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
898 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800899 }
900
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000901 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
902 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
903 ASSERT_EQ(OK, status);
904 }
905
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000906 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
907 std::optional<int32_t> expectedDisplayId,
908 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800909 InputEvent* event = consume();
910
911 ASSERT_NE(nullptr, event) << mName.c_str()
912 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800913 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700914 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800915 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800916
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000917 if (expectedDisplayId.has_value()) {
918 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
919 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800920
Tiger Huang8664f8c2018-10-11 19:14:35 +0800921 switch (expectedEventType) {
922 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800923 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
924 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000925 if (expectedFlags.has_value()) {
926 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
927 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800928 break;
929 }
930 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800931 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000932 assertMotionAction(expectedAction, motionEvent.getAction());
933
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000934 if (expectedFlags.has_value()) {
935 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
936 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800937 break;
938 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100939 case AINPUT_EVENT_TYPE_FOCUS: {
940 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
941 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800942 case AINPUT_EVENT_TYPE_CAPTURE: {
943 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
944 }
Antonio Kantekf16f2832021-09-28 04:39:20 +0000945 case AINPUT_EVENT_TYPE_TOUCH_MODE: {
946 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
947 }
arthurhungb89ccb02020-12-30 16:19:01 +0800948 case AINPUT_EVENT_TYPE_DRAG: {
949 FAIL() << "Use 'consumeDragEvent' for DRAG events";
950 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800951 default: {
952 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
953 }
954 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800955 }
956
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800957 MotionEvent* consumeMotion() {
958 InputEvent* event = consume();
959
960 if (event == nullptr) {
961 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
962 return nullptr;
963 }
964
965 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
966 ADD_FAILURE() << mName << " expected a MotionEvent, got "
967 << inputEventTypeToString(event->getType()) << " event";
968 return nullptr;
969 }
970 return static_cast<MotionEvent*>(event);
971 }
972
973 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
974 MotionEvent* motionEvent = consumeMotion();
975 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
976 ASSERT_THAT(*motionEvent, matcher);
977 }
978
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100979 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
980 InputEvent* event = consume();
981 ASSERT_NE(nullptr, event) << mName.c_str()
982 << ": consumer should have returned non-NULL event.";
983 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
984 << "Got " << inputEventTypeToString(event->getType())
985 << " event instead of FOCUS event";
986
987 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
988 << mName.c_str() << ": event displayId should always be NONE.";
989
990 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
991 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100992 }
993
Prabir Pradhan99987712020-11-10 18:43:05 -0800994 void consumeCaptureEvent(bool hasCapture) {
995 const InputEvent* event = consume();
996 ASSERT_NE(nullptr, event) << mName.c_str()
997 << ": consumer should have returned non-NULL event.";
998 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
999 << "Got " << inputEventTypeToString(event->getType())
1000 << " event instead of CAPTURE event";
1001
1002 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1003 << mName.c_str() << ": event displayId should always be NONE.";
1004
1005 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1006 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1007 }
1008
arthurhungb89ccb02020-12-30 16:19:01 +08001009 void consumeDragEvent(bool isExiting, float x, float y) {
1010 const InputEvent* event = consume();
1011 ASSERT_NE(nullptr, event) << mName.c_str()
1012 << ": consumer should have returned non-NULL event.";
1013 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
1014 << "Got " << inputEventTypeToString(event->getType())
1015 << " event instead of DRAG event";
1016
1017 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1018 << mName.c_str() << ": event displayId should always be NONE.";
1019
1020 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1021 EXPECT_EQ(isExiting, dragEvent.isExiting());
1022 EXPECT_EQ(x, dragEvent.getX());
1023 EXPECT_EQ(y, dragEvent.getY());
1024 }
1025
Antonio Kantekf16f2832021-09-28 04:39:20 +00001026 void consumeTouchModeEvent(bool inTouchMode) {
1027 const InputEvent* event = consume();
1028 ASSERT_NE(nullptr, event) << mName.c_str()
1029 << ": consumer should have returned non-NULL event.";
1030 ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
1031 << "Got " << inputEventTypeToString(event->getType())
1032 << " event instead of TOUCH_MODE event";
1033
1034 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1035 << mName.c_str() << ": event displayId should always be NONE.";
1036 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1037 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1038 }
1039
chaviwd1c23182019-12-20 18:44:56 -08001040 void assertNoEvents() {
1041 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001042 if (event == nullptr) {
1043 return;
1044 }
1045 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
1046 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1047 ADD_FAILURE() << "Received key event "
1048 << KeyEvent::actionToString(keyEvent.getAction());
1049 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
1050 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1051 ADD_FAILURE() << "Received motion event "
1052 << MotionEvent::actionToString(motionEvent.getAction());
1053 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
1054 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1055 ADD_FAILURE() << "Received focus event, hasFocus = "
1056 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -08001057 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
1058 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1059 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1060 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Antonio Kantekf16f2832021-09-28 04:39:20 +00001061 } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
1062 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1063 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1064 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001065 }
1066 FAIL() << mName.c_str()
1067 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001068 }
1069
1070 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1071
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001072 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1073
chaviwd1c23182019-12-20 18:44:56 -08001074protected:
1075 std::unique_ptr<InputConsumer> mConsumer;
1076 PreallocatedInputEventFactory mEventFactory;
1077
1078 std::string mName;
1079};
1080
chaviw3277faf2021-05-19 16:45:23 -05001081class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001082public:
1083 static const int32_t WIDTH = 600;
1084 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001085
Chris Yea209fde2020-07-22 13:54:51 -07001086 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001087 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001088 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001089 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001090 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001091 base::Result<std::unique_ptr<InputChannel>> channel =
1092 dispatcher->createInputChannel(name);
1093 token = (*channel)->getConnectionToken();
1094 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001095 }
1096
1097 inputApplicationHandle->updateInfo();
1098 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1099
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001100 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001101 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001102 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001103 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001104 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001105 mInfo.frameLeft = 0;
1106 mInfo.frameTop = 0;
1107 mInfo.frameRight = WIDTH;
1108 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001109 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001110 mInfo.globalScaleFactor = 1.0;
1111 mInfo.touchableRegion.clear();
1112 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001113 mInfo.ownerPid = WINDOW_PID;
1114 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001115 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001116 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001117 }
1118
Arthur Hungabbb9d82021-09-01 14:52:30 +00001119 sp<FakeWindowHandle> clone(
1120 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001121 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001122 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001123 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1124 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001125 return handle;
1126 }
1127
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001128 void setTouchable(bool touchable) {
1129 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1130 }
chaviwd1c23182019-12-20 18:44:56 -08001131
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001132 void setFocusable(bool focusable) {
1133 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1134 }
1135
1136 void setVisible(bool visible) {
1137 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1138 }
Vishnu Nair958da932020-08-21 17:12:37 -07001139
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001140 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001141 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001142 }
1143
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001144 void setPaused(bool paused) {
1145 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1146 }
1147
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001148 void setPreventSplitting(bool preventSplitting) {
1149 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001150 }
1151
1152 void setSlippery(bool slippery) {
1153 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1154 }
1155
1156 void setWatchOutsideTouch(bool watchOutside) {
1157 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1158 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001159
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001160 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1161
1162 void setInterceptsStylus(bool interceptsStylus) {
1163 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1164 }
1165
1166 void setDropInput(bool dropInput) {
1167 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1168 }
1169
1170 void setDropInputIfObscured(bool dropInputIfObscured) {
1171 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1172 }
1173
1174 void setNoInputChannel(bool noInputChannel) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1176 }
1177
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001178 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1179
chaviw3277faf2021-05-19 16:45:23 -05001180 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001181
Bernardo Rufino7393d172021-02-26 13:56:11 +00001182 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1183
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001184 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001185 mInfo.frameLeft = frame.left;
1186 mInfo.frameTop = frame.top;
1187 mInfo.frameRight = frame.right;
1188 mInfo.frameBottom = frame.bottom;
1189 mInfo.touchableRegion.clear();
1190 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001191
1192 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1193 ui::Transform translate;
1194 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1195 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001196 }
1197
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001198 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1199
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001200 void setIsWallpaper(bool isWallpaper) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1202 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001203
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001204 void setDupTouchToWallpaper(bool hasWallpaper) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1206 }
chaviwd1c23182019-12-20 18:44:56 -08001207
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001208 void setTrustedOverlay(bool trustedOverlay) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1210 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001211
chaviw9eaa22c2020-07-01 16:21:27 -07001212 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1213 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1214 }
1215
1216 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001217
yunho.shinf4a80b82020-11-16 21:13:57 +09001218 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1219
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001220 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1221 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1222 expectedFlags);
1223 }
1224
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001225 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1226 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1227 }
1228
Svet Ganov5d3bc372020-01-26 23:11:07 -08001229 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001230 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001231 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1232 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001233 }
1234
1235 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001236 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001237 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1238 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001239 }
1240
1241 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001242 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001243 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1244 }
1245
1246 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1247 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001248 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1249 expectedFlags);
1250 }
1251
Svet Ganov5d3bc372020-01-26 23:11:07 -08001252 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001253 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1254 int32_t expectedFlags = 0) {
1255 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1256 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001257 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1258 }
1259
1260 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001261 int32_t expectedFlags = 0) {
1262 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1263 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001264 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1265 }
1266
1267 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001268 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001269 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1270 expectedFlags);
1271 }
1272
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001273 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1274 int32_t expectedFlags = 0) {
1275 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1276 expectedFlags);
1277 }
1278
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001279 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1280 int32_t expectedFlags = 0) {
1281 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001282 ASSERT_NE(nullptr, event);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001283 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
1284 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1285 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1286 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1287 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1288 }
1289
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001290 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1291 ASSERT_NE(mInputReceiver, nullptr)
1292 << "Cannot consume events from a window with no receiver";
1293 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1294 }
1295
Prabir Pradhan99987712020-11-10 18:43:05 -08001296 void consumeCaptureEvent(bool hasCapture) {
1297 ASSERT_NE(mInputReceiver, nullptr)
1298 << "Cannot consume events from a window with no receiver";
1299 mInputReceiver->consumeCaptureEvent(hasCapture);
1300 }
1301
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001302 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1303 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001304 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001305 ASSERT_THAT(*motionEvent, matcher);
1306 }
1307
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001308 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1309 std::optional<int32_t> expectedDisplayId,
1310 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001311 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1312 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1313 expectedFlags);
1314 }
1315
arthurhungb89ccb02020-12-30 16:19:01 +08001316 void consumeDragEvent(bool isExiting, float x, float y) {
1317 mInputReceiver->consumeDragEvent(isExiting, x, y);
1318 }
1319
Antonio Kantekf16f2832021-09-28 04:39:20 +00001320 void consumeTouchModeEvent(bool inTouchMode) {
1321 ASSERT_NE(mInputReceiver, nullptr)
1322 << "Cannot consume events from a window with no receiver";
1323 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1324 }
1325
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001326 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001327 if (mInputReceiver == nullptr) {
1328 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1329 return std::nullopt;
1330 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001331 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001332 }
1333
1334 void finishEvent(uint32_t sequenceNum) {
1335 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1336 mInputReceiver->finishEvent(sequenceNum);
1337 }
1338
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001339 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1340 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1341 mInputReceiver->sendTimeline(inputEventId, timeline);
1342 }
1343
chaviwaf87b3e2019-10-01 16:59:28 -07001344 InputEvent* consume() {
1345 if (mInputReceiver == nullptr) {
1346 return nullptr;
1347 }
1348 return mInputReceiver->consume();
1349 }
1350
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001351 MotionEvent* consumeMotion() {
1352 InputEvent* event = consume();
1353 if (event == nullptr) {
1354 ADD_FAILURE() << "Consume failed : no event";
1355 return nullptr;
1356 }
1357 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1358 ADD_FAILURE() << "Instead of motion event, got "
1359 << inputEventTypeToString(event->getType());
1360 return nullptr;
1361 }
1362 return static_cast<MotionEvent*>(event);
1363 }
1364
Arthur Hungb92218b2018-08-14 12:00:21 +08001365 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001366 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001367 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001368 return; // Can't receive events if the window does not have input channel
1369 }
1370 ASSERT_NE(nullptr, mInputReceiver)
1371 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001372 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001373 }
1374
chaviwaf87b3e2019-10-01 16:59:28 -07001375 sp<IBinder> getToken() { return mInfo.token; }
1376
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001377 const std::string& getName() { return mName; }
1378
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001379 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1380 mInfo.ownerPid = ownerPid;
1381 mInfo.ownerUid = ownerUid;
1382 }
1383
Prabir Pradhanedd96402022-02-15 01:46:16 -08001384 int32_t getPid() const { return mInfo.ownerPid; }
1385
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001386 void destroyReceiver() { mInputReceiver = nullptr; }
1387
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001388 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1389
chaviwd1c23182019-12-20 18:44:56 -08001390private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001391 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001392 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001393 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001394};
1395
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001396std::atomic<int32_t> FakeWindowHandle::sId{1};
1397
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001398static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001399 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001400 int32_t displayId = ADISPLAY_ID_NONE,
1401 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001402 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001403 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1404 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001405 KeyEvent event;
1406 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1407
1408 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001409 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001410 INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
1411 repeatCount, currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001412
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001413 if (!allowKeyRepeat) {
1414 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1415 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001416 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001417 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001418}
1419
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001420static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001421 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001422 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId);
1423}
1424
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001425// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1426// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1427// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001428static InputEventInjectionResult injectKeyDownNoRepeat(
1429 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001430 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /* repeatCount */ 0, displayId,
1431 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
1432 /* allowKeyRepeat */ false);
1433}
1434
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001435static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001436 int32_t displayId = ADISPLAY_ID_NONE) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001437 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /* repeatCount */ 0, displayId);
1438}
1439
Garfield Tandf26e862020-07-01 20:18:19 -07001440class PointerBuilder {
1441public:
1442 PointerBuilder(int32_t id, int32_t toolType) {
1443 mProperties.clear();
1444 mProperties.id = id;
1445 mProperties.toolType = toolType;
1446 mCoords.clear();
1447 }
1448
1449 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1450
1451 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1452
1453 PointerBuilder& axis(int32_t axis, float value) {
1454 mCoords.setAxisValue(axis, value);
1455 return *this;
1456 }
1457
1458 PointerProperties buildProperties() const { return mProperties; }
1459
1460 PointerCoords buildCoords() const { return mCoords; }
1461
1462private:
1463 PointerProperties mProperties;
1464 PointerCoords mCoords;
1465};
1466
1467class MotionEventBuilder {
1468public:
1469 MotionEventBuilder(int32_t action, int32_t source) {
1470 mAction = action;
1471 mSource = source;
1472 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1473 }
1474
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001475 MotionEventBuilder& deviceId(int32_t deviceId) {
1476 mDeviceId = deviceId;
1477 return *this;
1478 }
1479
Garfield Tandf26e862020-07-01 20:18:19 -07001480 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1481 mEventTime = eventTime;
1482 return *this;
1483 }
1484
1485 MotionEventBuilder& displayId(int32_t displayId) {
1486 mDisplayId = displayId;
1487 return *this;
1488 }
1489
1490 MotionEventBuilder& actionButton(int32_t actionButton) {
1491 mActionButton = actionButton;
1492 return *this;
1493 }
1494
arthurhung6d4bed92021-03-17 11:59:33 +08001495 MotionEventBuilder& buttonState(int32_t buttonState) {
1496 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001497 return *this;
1498 }
1499
1500 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1501 mRawXCursorPosition = rawXCursorPosition;
1502 return *this;
1503 }
1504
1505 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1506 mRawYCursorPosition = rawYCursorPosition;
1507 return *this;
1508 }
1509
1510 MotionEventBuilder& pointer(PointerBuilder pointer) {
1511 mPointers.push_back(pointer);
1512 return *this;
1513 }
1514
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001515 MotionEventBuilder& addFlag(uint32_t flags) {
1516 mFlags |= flags;
1517 return *this;
1518 }
1519
Garfield Tandf26e862020-07-01 20:18:19 -07001520 MotionEvent build() {
1521 std::vector<PointerProperties> pointerProperties;
1522 std::vector<PointerCoords> pointerCoords;
1523 for (const PointerBuilder& pointer : mPointers) {
1524 pointerProperties.push_back(pointer.buildProperties());
1525 pointerCoords.push_back(pointer.buildCoords());
1526 }
1527
1528 // Set mouse cursor position for the most common cases to avoid boilerplate.
1529 if (mSource == AINPUT_SOURCE_MOUSE &&
1530 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1531 mPointers.size() == 1) {
1532 mRawXCursorPosition = pointerCoords[0].getX();
1533 mRawYCursorPosition = pointerCoords[0].getY();
1534 }
1535
1536 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001537 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001538 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001539 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001540 mButtonState, MotionClassification::NONE, identityTransform,
1541 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001542 mRawYCursorPosition, identityTransform, mEventTime, mEventTime,
1543 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001544
1545 return event;
1546 }
1547
1548private:
1549 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001550 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001551 int32_t mSource;
1552 nsecs_t mEventTime;
1553 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1554 int32_t mActionButton{0};
1555 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001556 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001557 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1558 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1559
1560 std::vector<PointerBuilder> mPointers;
1561};
1562
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001563static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001564 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001565 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001566 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1567 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1568 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1569 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001570}
1571
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001572static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001573 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001574 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001575 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001576 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1577 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001578 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001579 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1580 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001581 MotionEvent event = MotionEventBuilder(action, source)
1582 .displayId(displayId)
1583 .eventTime(eventTime)
1584 .rawXCursorPosition(cursorPosition.x)
1585 .rawYCursorPosition(cursorPosition.y)
1586 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1587 .x(position.x)
1588 .y(position.y))
1589 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001590
1591 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001592 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1593 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001594}
1595
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001596static InputEventInjectionResult injectMotionDown(
1597 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1598 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001599 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001600}
1601
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001602static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001603 int32_t source, int32_t displayId,
1604 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001605 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001606}
1607
Jackal Guof9696682018-10-05 12:23:23 +08001608static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1609 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1610 // Define a valid key event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001611 NotifyKeyArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1612 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1613 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001614
1615 return args;
1616}
1617
chaviwd1c23182019-12-20 18:44:56 -08001618static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1619 const std::vector<PointF>& points) {
1620 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001621 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1622 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1623 }
1624
chaviwd1c23182019-12-20 18:44:56 -08001625 PointerProperties pointerProperties[pointerCount];
1626 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001627
chaviwd1c23182019-12-20 18:44:56 -08001628 for (size_t i = 0; i < pointerCount; i++) {
1629 pointerProperties[i].clear();
1630 pointerProperties[i].id = i;
1631 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001632
chaviwd1c23182019-12-20 18:44:56 -08001633 pointerCoords[i].clear();
1634 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1635 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1636 }
Jackal Guof9696682018-10-05 12:23:23 +08001637
1638 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1639 // Define a valid motion event.
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001640 NotifyMotionArgs args(/* id */ 0, currentTime, 0 /*readTime*/, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001641 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1642 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001643 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1644 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001645 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1646 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001647
1648 return args;
1649}
1650
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001651static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1652 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1653}
1654
chaviwd1c23182019-12-20 18:44:56 -08001655static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1656 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1657}
1658
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001659static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1660 const PointerCaptureRequest& request) {
1661 return NotifyPointerCaptureChangedArgs(/* id */ 0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001662}
1663
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001664/**
1665 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1666 * broken channel.
1667 */
1668TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1670 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001671 sp<FakeWindowHandle>::make(application, mDispatcher,
1672 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001673
1674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1675
1676 // Window closes its channel, but the window remains.
1677 window->destroyReceiver();
1678 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1679}
1680
Arthur Hungb92218b2018-08-14 12:00:21 +08001681TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001683 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1684 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001685
Arthur Hung72d8dc32020-03-28 00:48:39 +00001686 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1688 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1689 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001690
1691 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001692 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001693}
1694
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001695TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001697 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1698 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001699
1700 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1701 // Inject a MotionEvent to an unknown display.
1702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1703 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1705
1706 // Window should receive motion event.
1707 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1708}
1709
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001711 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712 * This test serves as a sanity check for the next test, where setInputWindows is
1713 * called twice.
1714 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001715TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001717 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1718 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001719 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001720
1721 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001723 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1724 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726
1727 // Window should receive motion event.
1728 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1729}
1730
1731/**
1732 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001733 */
1734TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001736 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1737 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001738 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001739
1740 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1741 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001743 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1744 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001745 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001746
1747 // Window should receive motion event.
1748 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1749}
1750
Arthur Hungb92218b2018-08-14 12:00:21 +08001751// The foreground window should receive the first touch down event.
1752TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001754 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001755 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001756 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001757 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001758
Arthur Hung72d8dc32020-03-28 00:48:39 +00001759 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1761 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001763
1764 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001765 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001766 windowSecond->assertNoEvents();
1767}
1768
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001769/**
1770 * Two windows: A top window, and a wallpaper behind the window.
1771 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1772 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001773 * 1. foregroundWindow <-- dup touch to wallpaper
1774 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001775 */
1776TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1778 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001779 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001780 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001781 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001782 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001783 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001784
1785 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1787 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1788 {100, 200}))
1789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1790
1791 // Both foreground window and its wallpaper should receive the touch down
1792 foregroundWindow->consumeMotionDown();
1793 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1794
1795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1796 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1797 ADISPLAY_ID_DEFAULT, {110, 200}))
1798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1799
1800 foregroundWindow->consumeMotionMove();
1801 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1802
1803 // Now the foreground window goes away, but the wallpaper stays
1804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1805 foregroundWindow->consumeMotionCancel();
1806 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1807 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1808}
1809
1810/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001811 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1812 * with the following differences:
1813 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1814 * clean up the connection.
1815 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1816 * Ensure that there's no crash in the dispatcher.
1817 */
1818TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1820 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001821 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001822 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001823 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001824 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001825 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001826
1827 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1829 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1830 {100, 200}))
1831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1832
1833 // Both foreground window and its wallpaper should receive the touch down
1834 foregroundWindow->consumeMotionDown();
1835 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1836
1837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1838 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1839 ADISPLAY_ID_DEFAULT, {110, 200}))
1840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1841
1842 foregroundWindow->consumeMotionMove();
1843 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1844
1845 // Wallpaper closes its channel, but the window remains.
1846 wallpaperWindow->destroyReceiver();
1847 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1848
1849 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1850 // is no longer valid.
1851 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1852 foregroundWindow->consumeMotionCancel();
1853}
1854
Arthur Hungc539dbb2022-12-08 07:45:36 +00001855class ShouldSplitTouchFixture : public InputDispatcherTest,
1856 public ::testing::WithParamInterface<bool> {};
1857INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1858 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001859/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001860 * A single window that receives touch (on top), and a wallpaper window underneath it.
1861 * The top window gets a multitouch gesture.
1862 * Ensure that wallpaper gets the same gesture.
1863 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001864TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001865 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001866 sp<FakeWindowHandle> foregroundWindow =
1867 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1868 foregroundWindow->setDupTouchToWallpaper(true);
1869 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001870
1871 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001872 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001873 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001874
Arthur Hungc539dbb2022-12-08 07:45:36 +00001875 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876
1877 // Touch down on top window
1878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1879 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1880 {100, 100}))
1881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1882
1883 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001884 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1886
1887 // Second finger down on the top window
1888 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001889 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1891 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1892 .x(100)
1893 .y(100))
1894 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1895 .x(150)
1896 .y(150))
1897 .build();
1898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1899 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1900 InputEventInjectionSync::WAIT_FOR_RESULT))
1901 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1902
Arthur Hungc539dbb2022-12-08 07:45:36 +00001903 foregroundWindow->consumeMotionPointerDown(1 /* pointerIndex */);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1905 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001906
1907 const MotionEvent secondFingerUpEvent =
1908 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1909 .displayId(ADISPLAY_ID_DEFAULT)
1910 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1911 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1912 .x(100)
1913 .y(100))
1914 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1915 .x(150)
1916 .y(150))
1917 .build();
1918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1919 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1920 InputEventInjectionSync::WAIT_FOR_RESULT))
1921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1922 foregroundWindow->consumeMotionPointerUp(0);
1923 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1924
1925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1926 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1927 {100, 100}))
1928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1929 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1930 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001931}
1932
1933/**
1934 * Two windows: a window on the left and window on the right.
1935 * A third window, wallpaper, is behind both windows, and spans both top windows.
1936 * The first touch down goes to the left window. A second pointer touches down on the right window.
1937 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1938 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1939 * ACTION_POINTER_DOWN(1).
1940 */
1941TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1943 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001944 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001945 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001946 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001947
1948 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001949 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001950 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001951 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001952
1953 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001954 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001956 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001957
1958 mDispatcher->setInputWindows(
1959 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1960
1961 // Touch down on left window
1962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1963 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1964 {100, 100}))
1965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1966
1967 // Both foreground window and its wallpaper should receive the touch down
1968 leftWindow->consumeMotionDown();
1969 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1970
1971 // Second finger down on the right window
1972 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001973 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1975 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
1976 .x(100)
1977 .y(100))
1978 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
1979 .x(300)
1980 .y(100))
1981 .build();
1982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1983 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1984 InputEventInjectionSync::WAIT_FOR_RESULT))
1985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1986
1987 leftWindow->consumeMotionMove();
1988 // Since the touch is split, right window gets ACTION_DOWN
1989 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1990 wallpaperWindow->consumeMotionPointerDown(1 /* pointerIndex */, ADISPLAY_ID_DEFAULT,
1991 expectedWallpaperFlags);
1992
1993 // Now, leftWindow, which received the first finger, disappears.
1994 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1995 leftWindow->consumeMotionCancel();
1996 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1997 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1998
1999 // The pointer that's still down on the right window moves, and goes to the right window only.
2000 // As far as the dispatcher's concerned though, both pointers are still present.
2001 const MotionEvent secondFingerMoveEvent =
2002 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2003 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2004 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2005 .x(100)
2006 .y(100))
2007 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
2008 .x(310)
2009 .y(110))
2010 .build();
2011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2012 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2013 InputEventInjectionSync::WAIT_FOR_RESULT));
2014 rightWindow->consumeMotionMove();
2015
2016 leftWindow->assertNoEvents();
2017 rightWindow->assertNoEvents();
2018 wallpaperWindow->assertNoEvents();
2019}
2020
Arthur Hungc539dbb2022-12-08 07:45:36 +00002021/**
2022 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2023 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2024 * The right window should receive ACTION_DOWN.
2025 */
2026TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002027 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002028 sp<FakeWindowHandle> leftWindow =
2029 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2030 leftWindow->setFrame(Rect(0, 0, 200, 200));
2031 leftWindow->setDupTouchToWallpaper(true);
2032 leftWindow->setSlippery(true);
2033
2034 sp<FakeWindowHandle> rightWindow =
2035 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2036 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002037
2038 sp<FakeWindowHandle> wallpaperWindow =
2039 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2040 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002041
Arthur Hungc539dbb2022-12-08 07:45:36 +00002042 mDispatcher->setInputWindows(
2043 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002044
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2047 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002048 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002049 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050
2051 // Both foreground window and its wallpaper should receive the touch down
2052 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002053 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2054
Arthur Hungc539dbb2022-12-08 07:45:36 +00002055 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2058 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002059 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2060
Arthur Hungc539dbb2022-12-08 07:45:36 +00002061 leftWindow->consumeMotionCancel();
2062 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2063 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002064}
2065
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002066/**
2067 * On the display, have a single window, and also an area where there's no window.
2068 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2069 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2070 */
2071TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2072 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2073 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002074 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002075
2076 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
2077 NotifyMotionArgs args;
2078
2079 // Touch down on the empty space
2080 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}})));
2081
2082 mDispatcher->waitForIdle();
2083 window->assertNoEvents();
2084
2085 // Now touch down on the window with another pointer
2086 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}})));
2087 mDispatcher->waitForIdle();
2088 window->consumeMotionDown();
2089}
2090
2091/**
2092 * Same test as above, but instead of touching the empty space, the first touch goes to
2093 * non-touchable window.
2094 */
2095TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2097 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002098 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002099 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2100 window1->setTouchable(false);
2101 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002102 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002103 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2104
2105 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2106
2107 NotifyMotionArgs args;
2108 // Touch down on the non-touchable window
2109 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
2110
2111 mDispatcher->waitForIdle();
2112 window1->assertNoEvents();
2113 window2->assertNoEvents();
2114
2115 // Now touch down on the window with another pointer
2116 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
2117 mDispatcher->waitForIdle();
2118 window2->consumeMotionDown();
2119}
2120
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002121/**
2122 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2123 * to the event time of the first ACTION_DOWN sent to the particular window.
2124 */
2125TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2127 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002128 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002129 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2130 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002131 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002132 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2133
2134 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2135
2136 NotifyMotionArgs args;
2137 // Touch down on the first window
2138 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
2139
2140 mDispatcher->waitForIdle();
2141 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002142 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002143 window2->assertNoEvents();
2144 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2145 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2146 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2147
2148 // Now touch down on the window with another pointer
2149 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
2150 mDispatcher->waitForIdle();
2151 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002152 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002153 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2154 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2155 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2156 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2157
2158 // Now move the pointer on the second window
2159 mDispatcher->notifyMotion(
2160 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
2161 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002162 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002163
2164 // Now add new touch down on the second window
2165 mDispatcher->notifyMotion(
2166 &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
2167 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002168 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002169
2170 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2171 window1->consumeMotionMove();
2172 window1->assertNoEvents();
2173
2174 // Now move the pointer on the first window
2175 mDispatcher->notifyMotion(
2176 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}})));
2177 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002178 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002179
2180 mDispatcher->notifyMotion(&(
2181 args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
2182 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002183 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002184}
2185
Garfield Tandf26e862020-07-01 20:18:19 -07002186TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002187 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002188 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002189 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002190 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002191 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002192 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002193 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002194
2195 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2196
2197 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
2198
2199 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002201 injectMotionEvent(mDispatcher,
2202 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2203 AINPUT_SOURCE_MOUSE)
2204 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2205 .x(900)
2206 .y(400))
2207 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002208 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07002209
2210 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002212 injectMotionEvent(mDispatcher,
2213 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2214 AINPUT_SOURCE_MOUSE)
2215 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2216 .x(300)
2217 .y(400))
2218 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002219 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2220 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07002221
2222 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002224 injectMotionEvent(mDispatcher,
2225 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2226 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2227 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2228 .x(300)
2229 .y(400))
2230 .build()));
2231 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2232
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002234 injectMotionEvent(mDispatcher,
2235 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
2236 AINPUT_SOURCE_MOUSE)
2237 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2238 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2239 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2240 .x(300)
2241 .y(400))
2242 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002243 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07002244
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002246 injectMotionEvent(mDispatcher,
2247 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2248 AINPUT_SOURCE_MOUSE)
2249 .buttonState(0)
2250 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2251 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2252 .x(300)
2253 .y(400))
2254 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002255 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07002256
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002258 injectMotionEvent(mDispatcher,
2259 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
2260 .buttonState(0)
2261 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2262 .x(300)
2263 .y(400))
2264 .build()));
2265 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2266
2267 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002269 injectMotionEvent(mDispatcher,
2270 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2271 AINPUT_SOURCE_MOUSE)
2272 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2273 .x(900)
2274 .y(400))
2275 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002276 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2277 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002278
2279 // No more events
2280 windowLeft->assertNoEvents();
2281 windowRight->assertNoEvents();
2282}
2283
2284TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
2285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2286
2287 sp<FakeWindowHandle> spyWindow =
2288 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2289 spyWindow->setFrame(Rect(0, 0, 600, 800));
2290 spyWindow->setTrustedOverlay(true);
2291 spyWindow->setSpy(true);
2292 sp<FakeWindowHandle> window =
2293 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2294 window->setFrame(Rect(0, 0, 600, 800));
2295
2296 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2297 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2298
2299 // Send mouse cursor to the window
2300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2301 injectMotionEvent(mDispatcher,
2302 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2303 AINPUT_SOURCE_MOUSE)
2304 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2305 .x(100)
2306 .y(100))
2307 .build()));
2308
2309 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2310 WithSource(AINPUT_SOURCE_MOUSE)));
2311 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2312 WithSource(AINPUT_SOURCE_MOUSE)));
2313
2314 window->assertNoEvents();
2315 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07002316}
2317
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08002318TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
2319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2320
2321 sp<FakeWindowHandle> spyWindow =
2322 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2323 spyWindow->setFrame(Rect(0, 0, 600, 800));
2324 spyWindow->setTrustedOverlay(true);
2325 spyWindow->setSpy(true);
2326 sp<FakeWindowHandle> window =
2327 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2328 window->setFrame(Rect(0, 0, 600, 800));
2329
2330 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2331 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2332
2333 // Send mouse cursor to the window
2334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2335 injectMotionEvent(mDispatcher,
2336 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2337 AINPUT_SOURCE_MOUSE)
2338 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2339 .x(100)
2340 .y(100))
2341 .build()));
2342
2343 // Move mouse cursor
2344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2345 injectMotionEvent(mDispatcher,
2346 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2347 AINPUT_SOURCE_MOUSE)
2348 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2349 .x(110)
2350 .y(110))
2351 .build()));
2352
2353 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2354 WithSource(AINPUT_SOURCE_MOUSE)));
2355 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2356 WithSource(AINPUT_SOURCE_MOUSE)));
2357 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2358 WithSource(AINPUT_SOURCE_MOUSE)));
2359 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2360 WithSource(AINPUT_SOURCE_MOUSE)));
2361 // Touch down on the window
2362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2363 injectMotionEvent(mDispatcher,
2364 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2365 AINPUT_SOURCE_TOUCHSCREEN)
2366 .deviceId(SECOND_DEVICE_ID)
2367 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2368 .x(200)
2369 .y(200))
2370 .build()));
2371 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2372 WithSource(AINPUT_SOURCE_MOUSE)));
2373 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2374 WithSource(AINPUT_SOURCE_MOUSE)));
2375 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2376 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
2377 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2378 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
2379
2380 // pilfer the motion, retaining the gesture on the spy window.
2381 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2382 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
2383 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
2384
2385 // Touch UP on the window
2386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2387 injectMotionEvent(mDispatcher,
2388 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2389 AINPUT_SOURCE_TOUCHSCREEN)
2390 .deviceId(SECOND_DEVICE_ID)
2391 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2392 .x(200)
2393 .y(200))
2394 .build()));
2395 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
2396 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
2397
2398 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
2399 // to send a new gesture. It should again go to both windows (spy and the window below), just
2400 // like the first gesture did, before pilfering. The window configuration has not changed.
2401
2402 // One more tap - DOWN
2403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2404 injectMotionEvent(mDispatcher,
2405 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2406 AINPUT_SOURCE_TOUCHSCREEN)
2407 .deviceId(SECOND_DEVICE_ID)
2408 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2409 .x(250)
2410 .y(250))
2411 .build()));
2412 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2413 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
2414 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2415 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
2416
2417 // Touch UP on the window
2418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2419 injectMotionEvent(mDispatcher,
2420 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2421 AINPUT_SOURCE_TOUCHSCREEN)
2422 .deviceId(SECOND_DEVICE_ID)
2423 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2424 .x(250)
2425 .y(250))
2426 .build()));
2427 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
2428 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
2429 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
2430 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
2431
2432 window->assertNoEvents();
2433 spyWindow->assertNoEvents();
2434}
2435
Garfield Tandf26e862020-07-01 20:18:19 -07002436// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
2437// directly in this test.
2438TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002439 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002440 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002441 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002442 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002443
2444 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2445
2446 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002449 injectMotionEvent(mDispatcher,
2450 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2451 AINPUT_SOURCE_MOUSE)
2452 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2453 .x(300)
2454 .y(400))
2455 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002456 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07002457 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002459 injectMotionEvent(mDispatcher,
2460 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2461 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2462 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2463 .x(300)
2464 .y(400))
2465 .build()));
2466 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2467
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002469 injectMotionEvent(mDispatcher,
2470 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
2471 AINPUT_SOURCE_MOUSE)
2472 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2473 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2474 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2475 .x(300)
2476 .y(400))
2477 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002478 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07002479
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002481 injectMotionEvent(mDispatcher,
2482 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
2483 AINPUT_SOURCE_MOUSE)
2484 .buttonState(0)
2485 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2486 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2487 .x(300)
2488 .y(400))
2489 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002490 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07002491
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002493 injectMotionEvent(mDispatcher,
2494 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
2495 .buttonState(0)
2496 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2497 .x(300)
2498 .y(400))
2499 .build()));
2500 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2501
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002503 injectMotionEvent(mDispatcher,
2504 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
2505 AINPUT_SOURCE_MOUSE)
2506 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2507 .x(300)
2508 .y(400))
2509 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002510 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
Garfield Tandf26e862020-07-01 20:18:19 -07002511}
2512
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002513/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00002514 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
2515 * is generated.
2516 */
2517TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
2518 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2519 sp<FakeWindowHandle> window =
2520 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2521 window->setFrame(Rect(0, 0, 1200, 800));
2522
2523 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2524
2525 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2526
2527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2528 injectMotionEvent(mDispatcher,
2529 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2530 AINPUT_SOURCE_MOUSE)
2531 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2532 .x(300)
2533 .y(400))
2534 .build()));
2535 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2536
2537 // Remove the window, but keep the channel.
2538 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2539 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2540}
2541
2542/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002543 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00002544 * The tap causes a HOVER_EXIT event to be generated because the current event
2545 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002546 */
2547TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
2548 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2549 sp<FakeWindowHandle> window =
2550 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2551 window->setFrame(Rect(0, 0, 100, 100));
2552
2553 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2554
2555 // Inject a hover_move from mouse.
2556 NotifyMotionArgs motionArgs =
2557 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
2558 ADISPLAY_ID_DEFAULT, {{50, 50}});
2559 motionArgs.xCursorPosition = 50;
2560 motionArgs.yCursorPosition = 50;
2561 mDispatcher->notifyMotion(&motionArgs);
2562 ASSERT_NO_FATAL_FAILURE(
2563 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
2564 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002565
2566 // Tap on the window
2567 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2568 ADISPLAY_ID_DEFAULT, {{10, 10}});
2569 mDispatcher->notifyMotion(&motionArgs);
2570 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00002571 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
2572 WithSource(AINPUT_SOURCE_MOUSE))));
2573
2574 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08002575 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
2576 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
2577
2578 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
2579 ADISPLAY_ID_DEFAULT, {{10, 10}});
2580 mDispatcher->notifyMotion(&motionArgs);
2581 ASSERT_NO_FATAL_FAILURE(
2582 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
2583 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
2584}
2585
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002586TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
2587 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2588 sp<FakeWindowHandle> windowDefaultDisplay =
2589 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
2590 ADISPLAY_ID_DEFAULT);
2591 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
2592 sp<FakeWindowHandle> windowSecondDisplay =
2593 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
2594 SECOND_DISPLAY_ID);
2595 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
2596
2597 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
2598 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
2599
2600 // Set cursor position in window in default display and check that hover enter and move
2601 // events are generated.
2602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2603 injectMotionEvent(mDispatcher,
2604 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2605 AINPUT_SOURCE_MOUSE)
2606 .displayId(ADISPLAY_ID_DEFAULT)
2607 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2608 .x(300)
2609 .y(600))
2610 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002611 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002612
2613 // Remove all windows in secondary display and check that no event happens on window in
2614 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002615 mDispatcher->setInputWindows(
2616 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002617 windowDefaultDisplay->assertNoEvents();
2618
2619 // Move cursor position in window in default display and check that only hover move
2620 // event is generated and not hover enter event.
2621 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
2622 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
2623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2624 injectMotionEvent(mDispatcher,
2625 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2626 AINPUT_SOURCE_MOUSE)
2627 .displayId(ADISPLAY_ID_DEFAULT)
2628 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2629 .x(400)
2630 .y(700))
2631 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08002632 windowDefaultDisplay->consumeMotionEvent(
2633 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
2634 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02002635 windowDefaultDisplay->assertNoEvents();
2636}
2637
Garfield Tan00f511d2019-06-12 16:55:40 -07002638TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07002639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07002640
2641 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002642 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002643 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07002644 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002645 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002646 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07002647
2648 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2649
Arthur Hung72d8dc32020-03-28 00:48:39 +00002650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07002651
2652 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
2653 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07002655 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07002656 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08002657 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07002658 windowRight->assertNoEvents();
2659}
2660
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002661TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002662 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002663 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2664 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07002665 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002666
Arthur Hung72d8dc32020-03-28 00:48:39 +00002667 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07002668 setFocusedWindow(window);
2669
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01002670 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002671
2672 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2673 mDispatcher->notifyKey(&keyArgs);
2674
2675 // Window should receive key down event.
2676 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2677
2678 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
2679 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002680 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002681 mDispatcher->notifyDeviceReset(&args);
2682 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
2683 AKEY_EVENT_FLAG_CANCELED);
2684}
2685
2686TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07002687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002688 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2689 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002690
Arthur Hung72d8dc32020-03-28 00:48:39 +00002691 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002692
2693 NotifyMotionArgs motionArgs =
2694 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2695 ADISPLAY_ID_DEFAULT);
2696 mDispatcher->notifyMotion(&motionArgs);
2697
2698 // Window should receive motion down event.
2699 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2700
2701 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
2702 // on the app side.
Garfield Tanc51d1ba2020-01-28 13:24:04 -08002703 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002704 mDispatcher->notifyDeviceReset(&args);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08002705 window->consumeMotionEvent(
2706 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08002707}
2708
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002709TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
2710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002711 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2712 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002713 window->setFocusable(true);
2714
2715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2716 setFocusedWindow(window);
2717
2718 window->consumeFocusEvent(true);
2719
2720 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2721 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
2722 const nsecs_t injectTime = keyArgs.eventTime;
2723 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
2724 mDispatcher->notifyKey(&keyArgs);
2725 // The dispatching time should be always greater than or equal to intercept key timeout.
2726 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2727 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
2728 std::chrono::nanoseconds(interceptKeyTimeout).count());
2729}
2730
2731TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
2732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002733 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2734 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08002735 window->setFocusable(true);
2736
2737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2738 setFocusedWindow(window);
2739
2740 window->consumeFocusEvent(true);
2741
2742 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2743 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2744 mFakePolicy->setInterceptKeyTimeout(150ms);
2745 mDispatcher->notifyKey(&keyDown);
2746 mDispatcher->notifyKey(&keyUp);
2747
2748 // Window should receive key event immediately when same key up.
2749 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2750 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
2751}
2752
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002753/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08002754 * Two windows. First is a regular window. Second does not overlap with the first, and has
2755 * WATCH_OUTSIDE_TOUCH.
2756 * Both windows are owned by the same UID.
2757 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
2758 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
2759 */
2760TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
2761 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2762 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2763 "First Window", ADISPLAY_ID_DEFAULT);
2764 window->setFrame(Rect{0, 0, 100, 100});
2765
2766 sp<FakeWindowHandle> outsideWindow =
2767 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2768 ADISPLAY_ID_DEFAULT);
2769 outsideWindow->setFrame(Rect{100, 100, 200, 200});
2770 outsideWindow->setWatchOutsideTouch(true);
2771 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
2772 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
2773
2774 // Tap on first window.
2775 NotifyMotionArgs motionArgs =
2776 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2777 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
2778 mDispatcher->notifyMotion(&motionArgs);
2779 window->consumeMotionDown();
2780 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
2781 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
2782 outsideWindow->consumeMotionEvent(
2783 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
2784}
2785
2786/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002787 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
2788 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
2789 * ACTION_OUTSIDE event is sent per gesture.
2790 */
2791TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
2792 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
2793 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002794 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2795 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002796 window->setWatchOutsideTouch(true);
2797 window->setFrame(Rect{0, 0, 100, 100});
2798 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002799 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2800 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002801 secondWindow->setFrame(Rect{100, 100, 200, 200});
2802 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002803 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
2804 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002805 thirdWindow->setFrame(Rect{200, 200, 300, 300});
2806 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
2807
2808 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
2809 NotifyMotionArgs motionArgs =
2810 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2811 ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
2812 mDispatcher->notifyMotion(&motionArgs);
2813 window->assertNoEvents();
2814 secondWindow->assertNoEvents();
2815
2816 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
2817 // Now, `window` should get ACTION_OUTSIDE.
2818 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2819 {PointF{-10, -10}, PointF{105, 105}});
2820 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08002821 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
2822 window->consumeMotionEvent(
2823 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002824 secondWindow->consumeMotionDown();
2825 thirdWindow->assertNoEvents();
2826
2827 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
2828 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
2829 motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2830 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
2831 mDispatcher->notifyMotion(&motionArgs);
2832 window->assertNoEvents();
2833 secondWindow->consumeMotionMove();
2834 thirdWindow->consumeMotionDown();
2835}
2836
Prabir Pradhan814fe082022-07-22 20:22:18 +00002837TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
2838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002839 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2840 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00002841 window->setFocusable(true);
2842
2843 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
2844 setFocusedWindow(window);
2845
2846 window->consumeFocusEvent(true);
2847
2848 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
2849 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
2850 mDispatcher->notifyKey(&keyDown);
2851 mDispatcher->notifyKey(&keyUp);
2852
2853 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
2854 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
2855
2856 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
2857 mDispatcher->onWindowInfosChanged({}, {});
2858
2859 window->consumeFocusEvent(false);
2860
2861 mDispatcher->notifyKey(&keyDown);
2862 mDispatcher->notifyKey(&keyUp);
2863 window->assertNoEvents();
2864}
2865
Arthur Hung96483742022-11-15 03:30:48 +00002866TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
2867 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2868 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
2869 "Fake Window", ADISPLAY_ID_DEFAULT);
2870 // Ensure window is non-split and have some transform.
2871 window->setPreventSplitting(true);
2872 window->setWindowOffset(20, 40);
2873 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
2874
2875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2876 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2877 {50, 50}))
2878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2879 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2880
2881 const MotionEvent secondFingerDownEvent =
2882 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2883 .displayId(ADISPLAY_ID_DEFAULT)
2884 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2885 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
2886 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
2887 .x(-30)
2888 .y(-50))
2889 .build();
2890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2891 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2892 InputEventInjectionSync::WAIT_FOR_RESULT))
2893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2894
2895 const MotionEvent* event = window->consumeMotion();
2896 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
2897 EXPECT_EQ(70, event->getX(0)); // 50 + 20
2898 EXPECT_EQ(90, event->getY(0)); // 50 + 40
2899 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
2900 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
2901}
2902
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00002903/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002904 * Ensure the correct coordinate spaces are used by InputDispatcher.
2905 *
2906 * InputDispatcher works in the display space, so its coordinate system is relative to the display
2907 * panel. Windows get events in the window space, and get raw coordinates in the logical display
2908 * space.
2909 */
2910class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
2911public:
2912 void SetUp() override {
2913 InputDispatcherTest::SetUp();
2914 mDisplayInfos.clear();
2915 mWindowInfos.clear();
2916 }
2917
2918 void addDisplayInfo(int displayId, const ui::Transform& transform) {
2919 gui::DisplayInfo info;
2920 info.displayId = displayId;
2921 info.transform = transform;
2922 mDisplayInfos.push_back(std::move(info));
2923 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2924 }
2925
2926 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
2927 mWindowInfos.push_back(*windowHandle->getInfo());
2928 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
2929 }
2930
2931 // Set up a test scenario where the display has a scaled projection and there are two windows
2932 // on the display.
2933 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
2934 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
2935 // respectively.
2936 ui::Transform displayTransform;
2937 displayTransform.set(2, 0, 0, 4);
2938 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
2939
2940 std::shared_ptr<FakeApplicationHandle> application =
2941 std::make_shared<FakeApplicationHandle>();
2942
2943 // Add two windows to the display. Their frames are represented in the display space.
2944 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002945 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
2946 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002947 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
2948 addWindow(firstWindow);
2949
2950 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002951 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
2952 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07002953 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
2954 addWindow(secondWindow);
2955 return {std::move(firstWindow), std::move(secondWindow)};
2956 }
2957
2958private:
2959 std::vector<gui::DisplayInfo> mDisplayInfos;
2960 std::vector<gui::WindowInfo> mWindowInfos;
2961};
2962
2963TEST_F(InputDispatcherDisplayProjectionTest, HitTestsInDisplaySpace) {
2964 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2965 // Send down to the first window. The point is represented in the display space. The point is
2966 // selected so that if the hit test was done with the transform applied to it, then it would
2967 // end up in the incorrect window.
2968 NotifyMotionArgs downMotionArgs =
2969 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
2970 ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
2971 mDispatcher->notifyMotion(&downMotionArgs);
2972
2973 firstWindow->consumeMotionDown();
2974 secondWindow->assertNoEvents();
2975}
2976
2977// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
2978// the event should be treated as being in the logical display space.
2979TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
2980 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2981 // Send down to the first window. The point is represented in the logical display space. The
2982 // point is selected so that if the hit test was done in logical display space, then it would
2983 // end up in the incorrect window.
2984 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2985 PointF{75 * 2, 55 * 4});
2986
2987 firstWindow->consumeMotionDown();
2988 secondWindow->assertNoEvents();
2989}
2990
Prabir Pradhandaa2f142021-12-10 09:30:08 +00002991// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
2992// event should be treated as being in the logical display space.
2993TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
2994 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
2995
2996 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
2997 ui::Transform injectedEventTransform;
2998 injectedEventTransform.set(matrix);
2999 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
3000 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
3001
3002 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3003 .displayId(ADISPLAY_ID_DEFAULT)
3004 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
3005 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3006 .x(untransformedPoint.x)
3007 .y(untransformedPoint.y))
3008 .build();
3009 event.transform(matrix);
3010
3011 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
3012 InputEventInjectionSync::WAIT_FOR_RESULT);
3013
3014 firstWindow->consumeMotionDown();
3015 secondWindow->assertNoEvents();
3016}
3017
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003018TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
3019 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3020
3021 // Send down to the second window.
3022 NotifyMotionArgs downMotionArgs =
3023 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3024 ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
3025 mDispatcher->notifyMotion(&downMotionArgs);
3026
3027 firstWindow->assertNoEvents();
3028 const MotionEvent* event = secondWindow->consumeMotion();
3029 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
3030
3031 // Ensure that the events from the "getRaw" API are in logical display coordinates.
3032 EXPECT_EQ(300, event->getRawX(0));
3033 EXPECT_EQ(880, event->getRawY(0));
3034
3035 // Ensure that the x and y values are in the window's coordinate space.
3036 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
3037 // the logical display space. This will be the origin of the window space.
3038 EXPECT_EQ(100, event->getX(0));
3039 EXPECT_EQ(80, event->getY(0));
3040}
3041
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003042using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
3043 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003044
3045class TransferTouchFixture : public InputDispatcherTest,
3046 public ::testing::WithParamInterface<TransferFunction> {};
3047
3048TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07003049 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08003050
3051 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003052 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003053 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3054 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00003055 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003056 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003057 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3058 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00003059 sp<FakeWindowHandle> wallpaper =
3060 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
3061 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003062 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00003063 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003064
3065 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003066 NotifyMotionArgs downMotionArgs =
3067 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3068 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003069 mDispatcher->notifyMotion(&downMotionArgs);
Arthur Hungc539dbb2022-12-08 07:45:36 +00003070
Svet Ganov5d3bc372020-01-26 23:11:07 -08003071 // Only the first window should get the down event
3072 firstWindow->consumeMotionDown();
3073 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00003074 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003075
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003076 // Transfer touch to the second window
3077 TransferFunction f = GetParam();
3078 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
3079 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003080 // The first window gets cancel and the second gets down
3081 firstWindow->consumeMotionCancel();
3082 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00003083 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003084
3085 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003086 NotifyMotionArgs upMotionArgs =
3087 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3088 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003089 mDispatcher->notifyMotion(&upMotionArgs);
3090 // The first window gets no events and the second gets up
3091 firstWindow->assertNoEvents();
3092 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00003093 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08003094}
3095
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003096/**
3097 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
3098 * from. When we have spy windows, there are several windows to choose from: either spy, or the
3099 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
3100 * natural to the user.
3101 * In this test, we are sending a pointer to both spy window and first window. We then try to
3102 * transfer touch to the second window. The dispatcher should identify the first window as the
3103 * one that should lose the gesture, and therefore the action should be to move the gesture from
3104 * the first window to the second.
3105 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
3106 * the other API, as well.
3107 */
3108TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
3109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3110
3111 // Create a couple of windows + a spy window
3112 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003113 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003114 spyWindow->setTrustedOverlay(true);
3115 spyWindow->setSpy(true);
3116 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003117 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003118 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003119 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003120
3121 // Add the windows to the dispatcher
3122 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
3123
3124 // Send down to the first window
3125 NotifyMotionArgs downMotionArgs =
3126 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3127 ADISPLAY_ID_DEFAULT);
3128 mDispatcher->notifyMotion(&downMotionArgs);
3129 // Only the first window and spy should get the down event
3130 spyWindow->consumeMotionDown();
3131 firstWindow->consumeMotionDown();
3132
3133 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
3134 // if f === 'transferTouch'.
3135 TransferFunction f = GetParam();
3136 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
3137 ASSERT_TRUE(success);
3138 // The first window gets cancel and the second gets down
3139 firstWindow->consumeMotionCancel();
3140 secondWindow->consumeMotionDown();
3141
3142 // Send up event to the second window
3143 NotifyMotionArgs upMotionArgs =
3144 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3145 ADISPLAY_ID_DEFAULT);
3146 mDispatcher->notifyMotion(&upMotionArgs);
3147 // The first window gets no events and the second+spy get up
3148 firstWindow->assertNoEvents();
3149 spyWindow->consumeMotionUp();
3150 secondWindow->consumeMotionUp();
3151}
3152
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003153TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07003154 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08003155
3156 PointF touchPoint = {10, 10};
3157
3158 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003159 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003160 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3161 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08003162 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003163 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003164 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3165 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08003166 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003167
3168 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00003169 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003170
3171 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003172 NotifyMotionArgs downMotionArgs =
3173 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3174 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003175 mDispatcher->notifyMotion(&downMotionArgs);
3176 // Only the first window should get the down event
3177 firstWindow->consumeMotionDown();
3178 secondWindow->assertNoEvents();
3179
3180 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003181 NotifyMotionArgs pointerDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003182 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003183 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003184 mDispatcher->notifyMotion(&pointerDownMotionArgs);
3185 // Only the first window should get the pointer down event
3186 firstWindow->consumeMotionPointerDown(1);
3187 secondWindow->assertNoEvents();
3188
3189 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003190 TransferFunction f = GetParam();
3191 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
3192 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003193 // The first window gets cancel and the second gets down and pointer down
3194 firstWindow->consumeMotionCancel();
3195 secondWindow->consumeMotionDown();
3196 secondWindow->consumeMotionPointerDown(1);
3197
3198 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003199 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003200 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003201 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003202 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3203 // The first window gets nothing and the second gets pointer up
3204 firstWindow->assertNoEvents();
3205 secondWindow->consumeMotionPointerUp(1);
3206
3207 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003208 NotifyMotionArgs upMotionArgs =
3209 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3210 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003211 mDispatcher->notifyMotion(&upMotionArgs);
3212 // The first window gets nothing and the second gets up
3213 firstWindow->assertNoEvents();
3214 secondWindow->consumeMotionUp();
3215}
3216
Arthur Hungc539dbb2022-12-08 07:45:36 +00003217TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
3218 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3219
3220 // Create a couple of windows
3221 sp<FakeWindowHandle> firstWindow =
3222 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3223 ADISPLAY_ID_DEFAULT);
3224 firstWindow->setDupTouchToWallpaper(true);
3225 sp<FakeWindowHandle> secondWindow =
3226 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3227 ADISPLAY_ID_DEFAULT);
3228 secondWindow->setDupTouchToWallpaper(true);
3229
3230 sp<FakeWindowHandle> wallpaper1 =
3231 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
3232 wallpaper1->setIsWallpaper(true);
3233
3234 sp<FakeWindowHandle> wallpaper2 =
3235 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
3236 wallpaper2->setIsWallpaper(true);
3237 // Add the windows to the dispatcher
3238 mDispatcher->setInputWindows(
3239 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
3240
3241 // Send down to the first window
3242 NotifyMotionArgs downMotionArgs =
3243 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3244 ADISPLAY_ID_DEFAULT);
3245 mDispatcher->notifyMotion(&downMotionArgs);
3246
3247 // Only the first window should get the down event
3248 firstWindow->consumeMotionDown();
3249 secondWindow->assertNoEvents();
3250 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
3251 wallpaper2->assertNoEvents();
3252
3253 // Transfer touch focus to the second window
3254 TransferFunction f = GetParam();
3255 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
3256 ASSERT_TRUE(success);
3257
3258 // The first window gets cancel and the second gets down
3259 firstWindow->consumeMotionCancel();
3260 secondWindow->consumeMotionDown();
3261 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
3262 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
3263
3264 // Send up event to the second window
3265 NotifyMotionArgs upMotionArgs =
3266 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3267 ADISPLAY_ID_DEFAULT);
3268 mDispatcher->notifyMotion(&upMotionArgs);
3269 // The first window gets no events and the second gets up
3270 firstWindow->assertNoEvents();
3271 secondWindow->consumeMotionUp();
3272 wallpaper1->assertNoEvents();
3273 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
3274}
3275
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003276// For the cases of single pointer touch and two pointers non-split touch, the api's
3277// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
3278// for the case where there are multiple pointers split across several windows.
3279INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
3280 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003281 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
3282 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003283 return dispatcher->transferTouch(destChannelToken,
3284 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003285 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003286 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
3287 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003288 return dispatcher->transferTouchFocus(from, to,
3289 false /*isDragAndDrop*/);
3290 }));
3291
Svet Ganov5d3bc372020-01-26 23:11:07 -08003292TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07003293 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08003294
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003295 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003296 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3297 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003298 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08003299
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003300 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003301 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3302 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003303 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08003304
3305 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00003306 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003307
3308 PointF pointInFirst = {300, 200};
3309 PointF pointInSecond = {300, 600};
3310
3311 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003312 NotifyMotionArgs firstDownMotionArgs =
3313 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3314 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003315 mDispatcher->notifyMotion(&firstDownMotionArgs);
3316 // Only the first window should get the down event
3317 firstWindow->consumeMotionDown();
3318 secondWindow->assertNoEvents();
3319
3320 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003321 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003322 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003323 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003324 mDispatcher->notifyMotion(&secondDownMotionArgs);
3325 // The first window gets a move and the second a down
3326 firstWindow->consumeMotionMove();
3327 secondWindow->consumeMotionDown();
3328
3329 // Transfer touch focus to the second window
3330 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
3331 // The first window gets cancel and the new gets pointer down (it already saw down)
3332 firstWindow->consumeMotionCancel();
3333 secondWindow->consumeMotionPointerDown(1);
3334
3335 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003336 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003337 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003338 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08003339 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3340 // The first window gets nothing and the second gets pointer up
3341 firstWindow->assertNoEvents();
3342 secondWindow->consumeMotionPointerUp(1);
3343
3344 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10003345 NotifyMotionArgs upMotionArgs =
3346 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3347 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08003348 mDispatcher->notifyMotion(&upMotionArgs);
3349 // The first window gets nothing and the second gets up
3350 firstWindow->assertNoEvents();
3351 secondWindow->consumeMotionUp();
3352}
3353
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003354// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
3355// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
3356// touch is not supported, so the touch should continue on those windows and the transferred-to
3357// window should get nothing.
3358TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
3359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3360
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003361 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003362 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3363 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003364 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003365
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003366 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003367 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3368 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003369 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003370
3371 // Add the windows to the dispatcher
3372 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
3373
3374 PointF pointInFirst = {300, 200};
3375 PointF pointInSecond = {300, 600};
3376
3377 // Send down to the first window
3378 NotifyMotionArgs firstDownMotionArgs =
3379 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3380 ADISPLAY_ID_DEFAULT, {pointInFirst});
3381 mDispatcher->notifyMotion(&firstDownMotionArgs);
3382 // Only the first window should get the down event
3383 firstWindow->consumeMotionDown();
3384 secondWindow->assertNoEvents();
3385
3386 // Send down to the second window
3387 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003388 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003389 {pointInFirst, pointInSecond});
3390 mDispatcher->notifyMotion(&secondDownMotionArgs);
3391 // The first window gets a move and the second a down
3392 firstWindow->consumeMotionMove();
3393 secondWindow->consumeMotionDown();
3394
3395 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003396 const bool transferred =
3397 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003398 // The 'transferTouch' call should not succeed, because there are 2 touched windows
3399 ASSERT_FALSE(transferred);
3400 firstWindow->assertNoEvents();
3401 secondWindow->assertNoEvents();
3402
3403 // The rest of the dispatch should proceed as normal
3404 // Send pointer up to the second window
3405 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003406 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00003407 {pointInFirst, pointInSecond});
3408 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3409 // The first window gets MOVE and the second gets pointer up
3410 firstWindow->consumeMotionMove();
3411 secondWindow->consumeMotionUp();
3412
3413 // Send up event to the first window
3414 NotifyMotionArgs upMotionArgs =
3415 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3416 ADISPLAY_ID_DEFAULT);
3417 mDispatcher->notifyMotion(&upMotionArgs);
3418 // The first window gets nothing and the second gets up
3419 firstWindow->consumeMotionUp();
3420 secondWindow->assertNoEvents();
3421}
3422
Arthur Hungabbb9d82021-09-01 14:52:30 +00003423// This case will create two windows and one mirrored window on the default display and mirror
3424// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
3425// the windows info of second display before default display.
3426TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
3427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3428 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003429 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003430 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003431 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003432 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003433 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003434
3435 sp<FakeWindowHandle> mirrorWindowInPrimary =
3436 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
3437 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003438
3439 sp<FakeWindowHandle> firstWindowInSecondary =
3440 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3441 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003442
3443 sp<FakeWindowHandle> secondWindowInSecondary =
3444 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3445 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003446
3447 // Update window info, let it find window handle of second display first.
3448 mDispatcher->setInputWindows(
3449 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
3450 {ADISPLAY_ID_DEFAULT,
3451 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
3452
3453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3454 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3455 {50, 50}))
3456 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3457
3458 // Window should receive motion event.
3459 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3460
3461 // Transfer touch focus
3462 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
3463 secondWindowInPrimary->getToken()));
3464 // The first window gets cancel.
3465 firstWindowInPrimary->consumeMotionCancel();
3466 secondWindowInPrimary->consumeMotionDown();
3467
3468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3469 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3470 ADISPLAY_ID_DEFAULT, {150, 50}))
3471 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3472 firstWindowInPrimary->assertNoEvents();
3473 secondWindowInPrimary->consumeMotionMove();
3474
3475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3476 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3477 {150, 50}))
3478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3479 firstWindowInPrimary->assertNoEvents();
3480 secondWindowInPrimary->consumeMotionUp();
3481}
3482
3483// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
3484// 'transferTouch' api.
3485TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
3486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3487 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003488 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003489 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003490 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003491 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00003492 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003493
3494 sp<FakeWindowHandle> mirrorWindowInPrimary =
3495 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
3496 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003497
3498 sp<FakeWindowHandle> firstWindowInSecondary =
3499 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3500 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003501
3502 sp<FakeWindowHandle> secondWindowInSecondary =
3503 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
3504 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003505
3506 // Update window info, let it find window handle of second display first.
3507 mDispatcher->setInputWindows(
3508 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
3509 {ADISPLAY_ID_DEFAULT,
3510 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
3511
3512 // Touch on second display.
3513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3514 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
3515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3516
3517 // Window should receive motion event.
3518 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
3519
3520 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07003521 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00003522
3523 // The first window gets cancel.
3524 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
3525 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
3526
3527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3528 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3529 SECOND_DISPLAY_ID, {150, 50}))
3530 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3531 firstWindowInPrimary->assertNoEvents();
3532 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
3533
3534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3535 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
3536 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3537 firstWindowInPrimary->assertNoEvents();
3538 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
3539}
3540
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003541TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003542 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003543 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3544 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003545
Vishnu Nair47074b82020-08-14 11:54:47 -07003546 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003547 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003548 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003549
3550 window->consumeFocusEvent(true);
3551
3552 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3553 mDispatcher->notifyKey(&keyArgs);
3554
3555 // Window should receive key down event.
3556 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3557}
3558
3559TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003560 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003561 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3562 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003563
Arthur Hung72d8dc32020-03-28 00:48:39 +00003564 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003565
3566 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3567 mDispatcher->notifyKey(&keyArgs);
3568 mDispatcher->waitForIdle();
3569
3570 window->assertNoEvents();
3571}
3572
3573// If a window is touchable, but does not have focus, it should receive motion events, but not keys
3574TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07003575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003576 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3577 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003578
Arthur Hung72d8dc32020-03-28 00:48:39 +00003579 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003580
3581 // Send key
3582 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3583 mDispatcher->notifyKey(&keyArgs);
3584 // Send motion
3585 NotifyMotionArgs motionArgs =
3586 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3587 ADISPLAY_ID_DEFAULT);
3588 mDispatcher->notifyMotion(&motionArgs);
3589
3590 // Window should receive only the motion event
3591 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3592 window->assertNoEvents(); // Key event or focus event will not be received
3593}
3594
arthurhungea3f4fc2020-12-21 23:18:53 +08003595TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
3596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3597
arthurhungea3f4fc2020-12-21 23:18:53 +08003598 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003599 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3600 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08003601 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08003602
arthurhungea3f4fc2020-12-21 23:18:53 +08003603 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003604 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3605 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08003606 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08003607
3608 // Add the windows to the dispatcher
3609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
3610
3611 PointF pointInFirst = {300, 200};
3612 PointF pointInSecond = {300, 600};
3613
3614 // Send down to the first window
3615 NotifyMotionArgs firstDownMotionArgs =
3616 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3617 ADISPLAY_ID_DEFAULT, {pointInFirst});
3618 mDispatcher->notifyMotion(&firstDownMotionArgs);
3619 // Only the first window should get the down event
3620 firstWindow->consumeMotionDown();
3621 secondWindow->assertNoEvents();
3622
3623 // Send down to the second window
3624 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003625 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08003626 {pointInFirst, pointInSecond});
3627 mDispatcher->notifyMotion(&secondDownMotionArgs);
3628 // The first window gets a move and the second a down
3629 firstWindow->consumeMotionMove();
3630 secondWindow->consumeMotionDown();
3631
3632 // Send pointer cancel to the second window
3633 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003634 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08003635 {pointInFirst, pointInSecond});
3636 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
3637 mDispatcher->notifyMotion(&pointerUpMotionArgs);
3638 // The first window gets move and the second gets cancel.
3639 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
3640 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
3641
3642 // Send up event.
3643 NotifyMotionArgs upMotionArgs =
3644 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3645 ADISPLAY_ID_DEFAULT);
3646 mDispatcher->notifyMotion(&upMotionArgs);
3647 // The first window gets up and the second gets nothing.
3648 firstWindow->consumeMotionUp();
3649 secondWindow->assertNoEvents();
3650}
3651
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00003652TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
3653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3654
3655 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003656 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00003657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3658 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
3659 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
3660 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
3661
3662 window->sendTimeline(1 /*inputEventId*/, graphicsTimeline);
3663 window->assertNoEvents();
3664 mDispatcher->waitForIdle();
3665}
3666
chaviwd1c23182019-12-20 18:44:56 -08003667class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00003668public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07003669 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003670 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07003671 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08003672 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07003673 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00003674 }
3675
chaviwd1c23182019-12-20 18:44:56 -08003676 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
3677
3678 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3679 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
3680 expectedDisplayId, expectedFlags);
3681 }
3682
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07003683 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
3684
3685 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
3686
chaviwd1c23182019-12-20 18:44:56 -08003687 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3688 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
3689 expectedDisplayId, expectedFlags);
3690 }
3691
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003692 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3693 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
3694 expectedDisplayId, expectedFlags);
3695 }
3696
chaviwd1c23182019-12-20 18:44:56 -08003697 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
3698 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
3699 expectedDisplayId, expectedFlags);
3700 }
3701
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003702 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003703 mInputReceiver->consumeMotionEvent(
3704 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3705 WithDisplayId(expectedDisplayId),
3706 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003707 }
3708
Arthur Hungfbfa5722021-11-16 02:45:54 +00003709 void consumeMotionPointerDown(int32_t pointerIdx) {
3710 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
3711 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
3712 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
3713 0 /*expectedFlags*/);
3714 }
3715
Evan Rosky84f07f02021-04-16 10:42:42 -07003716 MotionEvent* consumeMotion() {
3717 InputEvent* event = mInputReceiver->consume();
3718 if (!event) {
3719 ADD_FAILURE() << "No event was produced";
3720 return nullptr;
3721 }
3722 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
3723 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
3724 return nullptr;
3725 }
3726 return static_cast<MotionEvent*>(event);
3727 }
3728
chaviwd1c23182019-12-20 18:44:56 -08003729 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
3730
3731private:
3732 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00003733};
3734
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003735using InputDispatcherMonitorTest = InputDispatcherTest;
3736
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003737/**
3738 * Two entities that receive touch: A window, and a global monitor.
3739 * The touch goes to the window, and then the window disappears.
3740 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
3741 * for the monitor, as well.
3742 * 1. foregroundWindow
3743 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
3744 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003745TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3747 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003748 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003749
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003750 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00003751
3752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3754 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3755 {100, 200}))
3756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3757
3758 // Both the foreground window and the global monitor should receive the touch down
3759 window->consumeMotionDown();
3760 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
3761
3762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3763 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3764 ADISPLAY_ID_DEFAULT, {110, 200}))
3765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3766
3767 window->consumeMotionMove();
3768 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
3769
3770 // Now the foreground window goes away
3771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3772 window->consumeMotionCancel();
3773 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
3774
3775 // If more events come in, there will be no more foreground window to send them to. This will
3776 // cause a cancel for the monitor, as well.
3777 ASSERT_EQ(InputEventInjectionResult::FAILED,
3778 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3779 ADISPLAY_ID_DEFAULT, {120, 200}))
3780 << "Injection should fail because the window was removed";
3781 window->assertNoEvents();
3782 // Global monitor now gets the cancel
3783 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
3784}
3785
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003786TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07003787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3789 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003790 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00003791
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003792 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003793
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00003795 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00003797 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08003798 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003799}
3800
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003801TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
3802 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003803
Chris Yea209fde2020-07-22 13:54:51 -07003804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003805 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3806 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003807 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00003808
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00003810 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003811 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08003812 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003813 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003814
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003815 // Pilfer pointers from the monitor.
3816 // This should not do anything and the window should continue to receive events.
3817 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00003818
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003820 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
3821 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003823
3824 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
3825 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00003826}
3827
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003828TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07003829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003830 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3831 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07003832 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3833 window->setWindowOffset(20, 40);
3834 window->setWindowTransform(0, 1, -1, 0);
3835
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003836 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07003837
3838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3839 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
3840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3841 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3842 MotionEvent* event = monitor.consumeMotion();
3843 // Even though window has transform, gesture monitor must not.
3844 ASSERT_EQ(ui::Transform(), event->getTransform());
3845}
3846
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003847TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00003848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003849 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00003850
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003851 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00003852 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08003853 << "Injection should fail if there is a monitor, but no touchable window";
3854 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00003855}
3856
chaviw81e2bb92019-12-18 15:03:51 -08003857TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003858 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003859 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3860 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08003861
Arthur Hung72d8dc32020-03-28 00:48:39 +00003862 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08003863
3864 NotifyMotionArgs motionArgs =
3865 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3866 ADISPLAY_ID_DEFAULT);
3867
3868 mDispatcher->notifyMotion(&motionArgs);
3869 // Window should receive motion down event.
3870 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3871
3872 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08003873 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08003874 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
3875 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
3876 motionArgs.pointerCoords[0].getX() - 10);
3877
3878 mDispatcher->notifyMotion(&motionArgs);
3879 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
3880 0 /*expectedFlags*/);
3881}
3882
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003883/**
3884 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
3885 * the device default right away. In the test scenario, we check both the default value,
3886 * and the action of enabling / disabling.
3887 */
3888TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07003889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003890 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3891 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08003892 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003893
3894 // Set focused application.
3895 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003896 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003897
3898 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00003899 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003900 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003901 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3902
3903 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003904 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003905 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003906 window->consumeFocusEvent(false /*hasFocus*/, true /*inTouchMode*/);
3907
3908 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003909 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07003910 true /*hasPermission*/, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003911 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07003912 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003913 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003914 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003915 window->consumeFocusEvent(true /*hasFocus*/, false /*inTouchMode*/);
3916
3917 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07003918 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003919 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003920 window->consumeFocusEvent(false /*hasFocus*/, false /*inTouchMode*/);
3921
3922 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08003923 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07003924 true /*hasPermission*/, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00003925 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07003926 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00003927 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003928 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003929 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3930
3931 window->assertNoEvents();
3932}
3933
Gang Wange9087892020-01-07 12:17:14 -05003934TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003935 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003936 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3937 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05003938
3939 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07003940 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05003941
Arthur Hung72d8dc32020-03-28 00:48:39 +00003942 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003943 setFocusedWindow(window);
3944
Gang Wange9087892020-01-07 12:17:14 -05003945 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
3946
3947 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
3948 mDispatcher->notifyKey(&keyArgs);
3949
3950 InputEvent* event = window->consume();
3951 ASSERT_NE(event, nullptr);
3952
3953 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3954 ASSERT_NE(verified, nullptr);
3955 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
3956
3957 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
3958 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
3959 ASSERT_EQ(keyArgs.source, verified->source);
3960 ASSERT_EQ(keyArgs.displayId, verified->displayId);
3961
3962 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
3963
3964 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05003965 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08003966 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05003967 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
3968 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
3969 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
3970 ASSERT_EQ(0, verifiedKey.repeatCount);
3971}
3972
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003973TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07003974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003975 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3976 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003977
3978 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3979
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07003980 ui::Transform transform;
3981 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
3982
3983 gui::DisplayInfo displayInfo;
3984 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
3985 displayInfo.transform = transform;
3986
3987 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08003988
3989 NotifyMotionArgs motionArgs =
3990 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3991 ADISPLAY_ID_DEFAULT);
3992 mDispatcher->notifyMotion(&motionArgs);
3993
3994 InputEvent* event = window->consume();
3995 ASSERT_NE(event, nullptr);
3996
3997 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
3998 ASSERT_NE(verified, nullptr);
3999 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
4000
4001 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
4002 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
4003 EXPECT_EQ(motionArgs.source, verified->source);
4004 EXPECT_EQ(motionArgs.displayId, verified->displayId);
4005
4006 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
4007
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07004008 const vec2 rawXY =
4009 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
4010 motionArgs.pointerCoords[0].getXYValue());
4011 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
4012 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004013 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004014 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004015 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004016 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
4017 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
4018}
4019
chaviw09c8d2d2020-08-24 15:48:26 -07004020/**
4021 * Ensure that separate calls to sign the same data are generating the same key.
4022 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
4023 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
4024 * tests.
4025 */
4026TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
4027 KeyEvent event = getTestKeyEvent();
4028 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
4029
4030 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
4031 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
4032 ASSERT_EQ(hmac1, hmac2);
4033}
4034
4035/**
4036 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
4037 */
4038TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
4039 KeyEvent event = getTestKeyEvent();
4040 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
4041 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
4042
4043 verifiedEvent.deviceId += 1;
4044 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4045
4046 verifiedEvent.source += 1;
4047 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4048
4049 verifiedEvent.eventTimeNanos += 1;
4050 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4051
4052 verifiedEvent.displayId += 1;
4053 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4054
4055 verifiedEvent.action += 1;
4056 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4057
4058 verifiedEvent.downTimeNanos += 1;
4059 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4060
4061 verifiedEvent.flags += 1;
4062 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4063
4064 verifiedEvent.keyCode += 1;
4065 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4066
4067 verifiedEvent.scanCode += 1;
4068 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4069
4070 verifiedEvent.metaState += 1;
4071 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4072
4073 verifiedEvent.repeatCount += 1;
4074 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
4075}
4076
Vishnu Nair958da932020-08-21 17:12:37 -07004077TEST_F(InputDispatcherTest, SetFocusedWindow) {
4078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4079 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004080 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004081 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004082 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004083 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4084
4085 // Top window is also focusable but is not granted focus.
4086 windowTop->setFocusable(true);
4087 windowSecond->setFocusable(true);
4088 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
4089 setFocusedWindow(windowSecond);
4090
4091 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4093 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004094
4095 // Focused window should receive event.
4096 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
4097 windowTop->assertNoEvents();
4098}
4099
4100TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
4101 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4102 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004103 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004104 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4105
4106 window->setFocusable(true);
4107 // Release channel for window is no longer valid.
4108 window->releaseChannel();
4109 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4110 setFocusedWindow(window);
4111
4112 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004113 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4114 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004115
4116 // window channel is invalid, so it should not receive any input event.
4117 window->assertNoEvents();
4118}
4119
4120TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
4121 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4122 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004123 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004124 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07004125 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4126
Vishnu Nair958da932020-08-21 17:12:37 -07004127 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4128 setFocusedWindow(window);
4129
4130 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004131 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4132 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004133
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004134 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07004135 window->assertNoEvents();
4136}
4137
4138TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
4139 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4140 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004141 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004142 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004143 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004144 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4145
4146 windowTop->setFocusable(true);
4147 windowSecond->setFocusable(true);
4148 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
4149 setFocusedWindow(windowTop);
4150 windowTop->consumeFocusEvent(true);
4151
4152 setFocusedWindow(windowSecond, windowTop);
4153 windowSecond->consumeFocusEvent(true);
4154 windowTop->consumeFocusEvent(false);
4155
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4157 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004158
4159 // Focused window should receive event.
4160 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
4161}
4162
4163TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
4164 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4165 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004166 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004167 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004168 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004169 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4170
4171 windowTop->setFocusable(true);
4172 windowSecond->setFocusable(true);
4173 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
4174 setFocusedWindow(windowSecond, windowTop);
4175
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004176 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
4177 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07004178
4179 // Event should be dropped.
4180 windowTop->assertNoEvents();
4181 windowSecond->assertNoEvents();
4182}
4183
4184TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
4185 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4186 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004187 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004188 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004189 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
4190 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004191 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4192
4193 window->setFocusable(true);
4194 previousFocusedWindow->setFocusable(true);
4195 window->setVisible(false);
4196 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
4197 setFocusedWindow(previousFocusedWindow);
4198 previousFocusedWindow->consumeFocusEvent(true);
4199
4200 // Requesting focus on invisible window takes focus from currently focused window.
4201 setFocusedWindow(window);
4202 previousFocusedWindow->consumeFocusEvent(false);
4203
4204 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07004206 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004207 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07004208
4209 // Window does not get focus event or key down.
4210 window->assertNoEvents();
4211
4212 // Window becomes visible.
4213 window->setVisible(true);
4214 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4215
4216 // Window receives focus event.
4217 window->consumeFocusEvent(true);
4218 // Focused window receives key down.
4219 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4220}
4221
Vishnu Nair599f1412021-06-21 10:39:58 -07004222TEST_F(InputDispatcherTest, DisplayRemoved) {
4223 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4224 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004225 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07004226 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4227
4228 // window is granted focus.
4229 window->setFocusable(true);
4230 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4231 setFocusedWindow(window);
4232 window->consumeFocusEvent(true);
4233
4234 // When a display is removed window loses focus.
4235 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
4236 window->consumeFocusEvent(false);
4237}
4238
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004239/**
4240 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
4241 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
4242 * of the 'slipperyEnterWindow'.
4243 *
4244 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
4245 * a way so that the touched location is no longer covered by the top window.
4246 *
4247 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
4248 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
4249 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
4250 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
4251 * with ACTION_DOWN).
4252 * Thus, the touch has been transferred from the top window into the bottom window, because the top
4253 * window moved itself away from the touched location and had Flag::SLIPPERY.
4254 *
4255 * Even though the top window moved away from the touched location, it is still obscuring the bottom
4256 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
4257 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
4258 *
4259 * In this test, we ensure that the event received by the bottom window has
4260 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
4261 */
4262TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00004263 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
4264 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004265
4266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4267 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4268
4269 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004270 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08004271 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004272 // Make sure this one overlaps the bottom window
4273 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
4274 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
4275 // one. Windows with the same owner are not considered to be occluding each other.
4276 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
4277
4278 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004279 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004280 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
4281
4282 mDispatcher->setInputWindows(
4283 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
4284
4285 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
4286 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4287 ADISPLAY_ID_DEFAULT, {{50, 50}});
4288 mDispatcher->notifyMotion(&args);
4289 slipperyExitWindow->consumeMotionDown();
4290 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
4291 mDispatcher->setInputWindows(
4292 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
4293
4294 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4295 ADISPLAY_ID_DEFAULT, {{51, 51}});
4296 mDispatcher->notifyMotion(&args);
4297
4298 slipperyExitWindow->consumeMotionCancel();
4299
4300 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
4301 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
4302}
4303
Garfield Tan1c7bc862020-01-28 13:24:04 -08004304class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
4305protected:
4306 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
4307 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
4308
Chris Yea209fde2020-07-22 13:54:51 -07004309 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004310 sp<FakeWindowHandle> mWindow;
4311
4312 virtual void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004313 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Garfield Tan1c7bc862020-01-28 13:24:04 -08004314 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004315 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004316 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
4317 ASSERT_EQ(OK, mDispatcher->start());
4318
4319 setUpWindow();
4320 }
4321
4322 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07004323 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004324 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004325
Vishnu Nair47074b82020-08-14 11:54:47 -07004326 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004328 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004329 mWindow->consumeFocusEvent(true);
4330 }
4331
Chris Ye2ad95392020-09-01 13:44:44 -07004332 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08004333 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07004334 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004335 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
4336 mDispatcher->notifyKey(&keyArgs);
4337
4338 // Window should receive key down event.
4339 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4340 }
4341
4342 void expectKeyRepeatOnce(int32_t repeatCount) {
4343 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
4344 InputEvent* repeatEvent = mWindow->consume();
4345 ASSERT_NE(nullptr, repeatEvent);
4346
4347 uint32_t eventType = repeatEvent->getType();
4348 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
4349
4350 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
4351 uint32_t eventAction = repeatKeyEvent->getAction();
4352 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
4353 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
4354 }
4355
Chris Ye2ad95392020-09-01 13:44:44 -07004356 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08004357 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07004358 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08004359 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
4360 mDispatcher->notifyKey(&keyArgs);
4361
4362 // Window should receive key down event.
4363 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
4364 0 /*expectedFlags*/);
4365 }
4366};
4367
4368TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Chris Ye2ad95392020-09-01 13:44:44 -07004369 sendAndConsumeKeyDown(1 /* deviceId */);
4370 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4371 expectKeyRepeatOnce(repeatCount);
4372 }
4373}
4374
4375TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
4376 sendAndConsumeKeyDown(1 /* deviceId */);
4377 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4378 expectKeyRepeatOnce(repeatCount);
4379 }
4380 sendAndConsumeKeyDown(2 /* deviceId */);
4381 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08004382 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4383 expectKeyRepeatOnce(repeatCount);
4384 }
4385}
4386
4387TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Chris Ye2ad95392020-09-01 13:44:44 -07004388 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004389 expectKeyRepeatOnce(1 /*repeatCount*/);
Chris Ye2ad95392020-09-01 13:44:44 -07004390 sendAndConsumeKeyUp(1 /* deviceId */);
4391 mWindow->assertNoEvents();
4392}
4393
4394TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
4395 sendAndConsumeKeyDown(1 /* deviceId */);
4396 expectKeyRepeatOnce(1 /*repeatCount*/);
4397 sendAndConsumeKeyDown(2 /* deviceId */);
4398 expectKeyRepeatOnce(1 /*repeatCount*/);
4399 // Stale key up from device 1.
4400 sendAndConsumeKeyUp(1 /* deviceId */);
4401 // Device 2 is still down, keep repeating
4402 expectKeyRepeatOnce(2 /*repeatCount*/);
4403 expectKeyRepeatOnce(3 /*repeatCount*/);
4404 // Device 2 key up
4405 sendAndConsumeKeyUp(2 /* deviceId */);
4406 mWindow->assertNoEvents();
4407}
4408
4409TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
4410 sendAndConsumeKeyDown(1 /* deviceId */);
4411 expectKeyRepeatOnce(1 /*repeatCount*/);
4412 sendAndConsumeKeyDown(2 /* deviceId */);
4413 expectKeyRepeatOnce(1 /*repeatCount*/);
4414 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
4415 sendAndConsumeKeyUp(2 /* deviceId */);
4416 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08004417 mWindow->assertNoEvents();
4418}
4419
liushenxiang42232912021-05-21 20:24:09 +08004420TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
4421 sendAndConsumeKeyDown(DEVICE_ID);
4422 expectKeyRepeatOnce(1 /*repeatCount*/);
4423 NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
4424 mDispatcher->notifyDeviceReset(&args);
4425 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
4426 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
4427 mWindow->assertNoEvents();
4428}
4429
Garfield Tan1c7bc862020-01-28 13:24:04 -08004430TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Chris Ye2ad95392020-09-01 13:44:44 -07004431 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004432 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4433 InputEvent* repeatEvent = mWindow->consume();
4434 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
4435 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
4436 IdGenerator::getSource(repeatEvent->getId()));
4437 }
4438}
4439
4440TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Chris Ye2ad95392020-09-01 13:44:44 -07004441 sendAndConsumeKeyDown(1 /* deviceId */);
Garfield Tan1c7bc862020-01-28 13:24:04 -08004442
4443 std::unordered_set<int32_t> idSet;
4444 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
4445 InputEvent* repeatEvent = mWindow->consume();
4446 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
4447 int32_t id = repeatEvent->getId();
4448 EXPECT_EQ(idSet.end(), idSet.find(id));
4449 idSet.insert(id);
4450 }
4451}
4452
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004453/* Test InputDispatcher for MultiDisplay */
4454class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
4455public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004456 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004457 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08004458
Chris Yea209fde2020-07-22 13:54:51 -07004459 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004460 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004461 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004462
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004463 // Set focus window for primary display, but focused display would be second one.
4464 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07004465 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004466 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004467 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004468 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08004469
Chris Yea209fde2020-07-22 13:54:51 -07004470 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004471 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004472 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004473 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004474 // Set focus display to second one.
4475 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
4476 // Set focus window for second display.
4477 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07004478 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004479 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004480 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004481 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004482 }
4483
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004484 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004485 InputDispatcherTest::TearDown();
4486
Chris Yea209fde2020-07-22 13:54:51 -07004487 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004488 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07004489 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004490 windowInSecondary.clear();
4491 }
4492
4493protected:
Chris Yea209fde2020-07-22 13:54:51 -07004494 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004495 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07004496 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004497 sp<FakeWindowHandle> windowInSecondary;
4498};
4499
4500TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
4501 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4503 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004505 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08004506 windowInSecondary->assertNoEvents();
4507
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004508 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4510 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4511 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08004512 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004513 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08004514}
4515
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004516TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08004517 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4519 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004520 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004521 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08004522 windowInSecondary->assertNoEvents();
4523
4524 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004526 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08004527 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004528 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08004529
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004530 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00004531 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08004532
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004533 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004534 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
4535 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08004536
4537 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004538 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004539 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08004540 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004541 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08004542 windowInSecondary->assertNoEvents();
4543}
4544
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004545// Test per-display input monitors for motion event.
4546TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08004547 FakeMonitorReceiver monitorInPrimary =
4548 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4549 FakeMonitorReceiver monitorInSecondary =
4550 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004551
4552 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4554 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4555 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004556 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004557 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004558 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004559 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004560
4561 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4563 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4564 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004565 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004566 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004567 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08004568 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004569
4570 // Test inject a non-pointer motion event.
4571 // If specific a display, it will dispatch to the focused window of particular display,
4572 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4574 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
4575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004576 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004577 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004578 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08004579 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004580}
4581
4582// Test per-display input monitors for key event.
4583TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004584 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08004585 FakeMonitorReceiver monitorInPrimary =
4586 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4587 FakeMonitorReceiver monitorInSecondary =
4588 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004589
4590 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
4592 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004593 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08004594 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004595 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08004596 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08004597}
4598
Vishnu Nair958da932020-08-21 17:12:37 -07004599TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
4600 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004601 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07004602 secondWindowInPrimary->setFocusable(true);
4603 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
4604 setFocusedWindow(secondWindowInPrimary);
4605 windowInPrimary->consumeFocusEvent(false);
4606 secondWindowInPrimary->consumeFocusEvent(true);
4607
4608 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
4610 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07004611 windowInPrimary->assertNoEvents();
4612 windowInSecondary->assertNoEvents();
4613 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4614}
4615
Arthur Hungdfd528e2021-12-08 13:23:04 +00004616TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
4617 FakeMonitorReceiver monitorInPrimary =
4618 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
4619 FakeMonitorReceiver monitorInSecondary =
4620 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
4621
4622 // Test touch down on primary display.
4623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4624 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4626 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4627 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4628
4629 // Test touch down on second display.
4630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4631 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
4632 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4633 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
4634 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
4635
4636 // Trigger cancel touch.
4637 mDispatcher->cancelCurrentTouch();
4638 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4639 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4640 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
4641 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
4642
4643 // Test inject a move motion event, no window/monitor should receive the event.
4644 ASSERT_EQ(InputEventInjectionResult::FAILED,
4645 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4646 ADISPLAY_ID_DEFAULT, {110, 200}))
4647 << "Inject motion event should return InputEventInjectionResult::FAILED";
4648 windowInPrimary->assertNoEvents();
4649 monitorInPrimary.assertNoEvents();
4650
4651 ASSERT_EQ(InputEventInjectionResult::FAILED,
4652 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4653 SECOND_DISPLAY_ID, {110, 200}))
4654 << "Inject motion event should return InputEventInjectionResult::FAILED";
4655 windowInSecondary->assertNoEvents();
4656 monitorInSecondary.assertNoEvents();
4657}
4658
Jackal Guof9696682018-10-05 12:23:23 +08004659class InputFilterTest : public InputDispatcherTest {
4660protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004661 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
4662 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08004663 NotifyMotionArgs motionArgs;
4664
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004665 motionArgs =
4666 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08004667 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004668 motionArgs =
4669 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08004670 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004671 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08004672 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004673 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
4674 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08004675 } else {
4676 mFakePolicy->assertFilterInputEventWasNotCalled();
4677 }
4678 }
4679
4680 void testNotifyKey(bool expectToBeFiltered) {
4681 NotifyKeyArgs keyArgs;
4682
4683 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
4684 mDispatcher->notifyKey(&keyArgs);
4685 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
4686 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004687 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08004688
4689 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08004690 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08004691 } else {
4692 mFakePolicy->assertFilterInputEventWasNotCalled();
4693 }
4694 }
4695};
4696
4697// Test InputFilter for MotionEvent
4698TEST_F(InputFilterTest, MotionEvent_InputFilter) {
4699 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
4700 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
4701 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
4702
4703 // Enable InputFilter
4704 mDispatcher->setInputFilterEnabled(true);
4705 // Test touch on both primary and second display, and check if both events are filtered.
4706 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
4707 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
4708
4709 // Disable InputFilter
4710 mDispatcher->setInputFilterEnabled(false);
4711 // Test touch on both primary and second display, and check if both events aren't filtered.
4712 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
4713 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
4714}
4715
4716// Test InputFilter for KeyEvent
4717TEST_F(InputFilterTest, KeyEvent_InputFilter) {
4718 // Since the InputFilter is disabled by default, check if key event aren't filtered.
4719 testNotifyKey(/*expectToBeFiltered*/ false);
4720
4721 // Enable InputFilter
4722 mDispatcher->setInputFilterEnabled(true);
4723 // Send a key event, and check if it is filtered.
4724 testNotifyKey(/*expectToBeFiltered*/ true);
4725
4726 // Disable InputFilter
4727 mDispatcher->setInputFilterEnabled(false);
4728 // Send a key event, and check if it isn't filtered.
4729 testNotifyKey(/*expectToBeFiltered*/ false);
4730}
4731
Prabir Pradhan81420cc2021-09-06 10:28:50 -07004732// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
4733// logical display coordinate space.
4734TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
4735 ui::Transform firstDisplayTransform;
4736 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
4737 ui::Transform secondDisplayTransform;
4738 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
4739
4740 std::vector<gui::DisplayInfo> displayInfos(2);
4741 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
4742 displayInfos[0].transform = firstDisplayTransform;
4743 displayInfos[1].displayId = SECOND_DISPLAY_ID;
4744 displayInfos[1].transform = secondDisplayTransform;
4745
4746 mDispatcher->onWindowInfosChanged({}, displayInfos);
4747
4748 // Enable InputFilter
4749 mDispatcher->setInputFilterEnabled(true);
4750
4751 // Ensure the correct transforms are used for the displays.
4752 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
4753 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
4754}
4755
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004756class InputFilterInjectionPolicyTest : public InputDispatcherTest {
4757protected:
4758 virtual void SetUp() override {
4759 InputDispatcherTest::SetUp();
4760
4761 /**
4762 * We don't need to enable input filter to test the injected event policy, but we enabled it
4763 * here to make the tests more realistic, since this policy only matters when inputfilter is
4764 * on.
4765 */
4766 mDispatcher->setInputFilterEnabled(true);
4767
4768 std::shared_ptr<InputApplicationHandle> application =
4769 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004770 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
4771 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004772
4773 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4774 mWindow->setFocusable(true);
4775 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
4776 setFocusedWindow(mWindow);
4777 mWindow->consumeFocusEvent(true);
4778 }
4779
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004780 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
4781 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004782 KeyEvent event;
4783
4784 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4785 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
4786 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
4787 KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
4788 const int32_t additionalPolicyFlags =
4789 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
4790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan5735a322022-04-11 17:23:34 +00004791 mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004792 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
4793 policyFlags | additionalPolicyFlags));
4794
4795 InputEvent* received = mWindow->consume();
4796 ASSERT_NE(nullptr, received);
4797 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004798 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
4799 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
4800 ASSERT_EQ(flags, keyEvent.getFlags());
4801 }
4802
4803 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
4804 int32_t flags) {
4805 MotionEvent event;
4806 PointerProperties pointerProperties[1];
4807 PointerCoords pointerCoords[1];
4808 pointerProperties[0].clear();
4809 pointerProperties[0].id = 0;
4810 pointerCoords[0].clear();
4811 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
4812 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
4813
4814 ui::Transform identityTransform;
4815 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4816 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
4817 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
4818 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
4819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07004820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07004821 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004822 /*pointerCount*/ 1, pointerProperties, pointerCoords);
4823
4824 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
4825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan5735a322022-04-11 17:23:34 +00004826 mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004827 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
4828 policyFlags | additionalPolicyFlags));
4829
4830 InputEvent* received = mWindow->consume();
4831 ASSERT_NE(nullptr, received);
4832 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
4833 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
4834 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
4835 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004836 }
4837
4838private:
4839 sp<FakeWindowHandle> mWindow;
4840};
4841
4842TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004843 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
4844 // filter. Without it, the event will no different from a regularly injected event, and the
4845 // injected device id will be overwritten.
4846 testInjectedKey(POLICY_FLAG_FILTERED, 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4847 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004848}
4849
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004850TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004851 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004852 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4853 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4854}
4855
4856TEST_F(InputFilterInjectionPolicyTest,
4857 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
4858 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
4859 3 /*injectedDeviceId*/, 3 /*resolvedDeviceId*/,
4860 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004861}
4862
4863TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
4864 testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00004865 VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/, 0 /*flags*/);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00004866}
4867
chaviwfd6d3512019-03-25 13:23:49 -07004868class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004869 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07004870 InputDispatcherTest::SetUp();
4871
Chris Yea209fde2020-07-22 13:54:51 -07004872 std::shared_ptr<FakeApplicationHandle> application =
4873 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004874 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004875 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004876 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07004877
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004878 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004879 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004880 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07004881
4882 // Set focused application.
4883 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004884 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07004885
4886 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00004887 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004888 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004889 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07004890 }
4891
Prabir Pradhan3608aad2019-10-02 17:08:26 -07004892 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07004893 InputDispatcherTest::TearDown();
4894
4895 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004896 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07004897 }
4898
4899protected:
4900 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004901 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004902 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07004903};
4904
4905// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4906// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
4907// the onPointerDownOutsideFocus callback.
4908TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004910 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4911 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004912 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004913 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004914
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004915 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07004916 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
4917}
4918
4919// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
4920// DOWN on the window that doesn't have focus. Ensure no window received the
4921// onPointerDownOutsideFocus callback.
4922TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004924 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004926 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004927
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004928 ASSERT_TRUE(mDispatcher->waitForIdle());
4929 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004930}
4931
4932// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
4933// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
4934TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08004935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4936 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004937 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004938 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07004939
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004940 ASSERT_TRUE(mDispatcher->waitForIdle());
4941 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004942}
4943
4944// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
4945// DOWN on the window that already has focus. Ensure no window received the
4946// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004947TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08004949 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07004950 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07004952 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07004953
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004954 ASSERT_TRUE(mDispatcher->waitForIdle());
4955 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07004956}
4957
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08004958// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
4959// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
4960TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
4961 const MotionEvent event =
4962 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4963 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
4964 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
4965 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
4966 .build();
4967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
4968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4969 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
4970
4971 ASSERT_TRUE(mDispatcher->waitForIdle());
4972 mFakePolicy->assertOnPointerDownWasNotCalled();
4973 // Ensure that the unfocused window did not receive any FOCUS events.
4974 mUnfocusedWindow->assertNoEvents();
4975}
4976
chaviwaf87b3e2019-10-01 16:59:28 -07004977// These tests ensures we can send touch events to a single client when there are multiple input
4978// windows that point to the same client token.
4979class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
4980 virtual void SetUp() override {
4981 InputDispatcherTest::SetUp();
4982
Chris Yea209fde2020-07-22 13:54:51 -07004983 std::shared_ptr<FakeApplicationHandle> application =
4984 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004985 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
4986 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07004987 mWindow1->setFrame(Rect(0, 0, 100, 100));
4988
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004989 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
4990 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07004991 mWindow2->setFrame(Rect(100, 100, 200, 200));
4992
Arthur Hung72d8dc32020-03-28 00:48:39 +00004993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07004994 }
4995
4996protected:
4997 sp<FakeWindowHandle> mWindow1;
4998 sp<FakeWindowHandle> mWindow2;
4999
5000 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05005001 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07005002 vec2 vals = windowInfo->transform.transform(point.x, point.y);
5003 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07005004 }
5005
5006 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
5007 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005008 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07005009 InputEvent* event = window->consume();
5010
5011 ASSERT_NE(nullptr, event) << name.c_str()
5012 << ": consumer should have returned non-NULL event.";
5013
5014 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
5015 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
5016 << " event, got " << inputEventTypeToString(event->getType()) << " event";
5017
5018 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005019 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08005020 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07005021
5022 for (size_t i = 0; i < points.size(); i++) {
5023 float expectedX = points[i].x;
5024 float expectedY = points[i].y;
5025
5026 EXPECT_EQ(expectedX, motionEvent.getX(i))
5027 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
5028 << ", got " << motionEvent.getX(i);
5029 EXPECT_EQ(expectedY, motionEvent.getY(i))
5030 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
5031 << ", got " << motionEvent.getY(i);
5032 }
5033 }
chaviw9eaa22c2020-07-01 16:21:27 -07005034
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005035 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07005036 std::vector<PointF> expectedPoints) {
5037 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
5038 ADISPLAY_ID_DEFAULT, touchedPoints);
5039 mDispatcher->notifyMotion(&motionArgs);
5040
5041 // Always consume from window1 since it's the window that has the InputReceiver
5042 consumeMotionEvent(mWindow1, action, expectedPoints);
5043 }
chaviwaf87b3e2019-10-01 16:59:28 -07005044};
5045
5046TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
5047 // Touch Window 1
5048 PointF touchedPoint = {10, 10};
5049 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07005050 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005051
5052 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07005053 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005054
5055 // Touch Window 2
5056 touchedPoint = {150, 150};
5057 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07005058 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005059}
5060
chaviw9eaa22c2020-07-01 16:21:27 -07005061TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
5062 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07005063 mWindow2->setWindowScale(0.5f, 0.5f);
5064
5065 // Touch Window 1
5066 PointF touchedPoint = {10, 10};
5067 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07005068 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005069 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07005070 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005071
5072 // Touch Window 2
5073 touchedPoint = {150, 150};
5074 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07005075 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
5076 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005077
chaviw9eaa22c2020-07-01 16:21:27 -07005078 // Update the transform so rotation is set
5079 mWindow2->setWindowTransform(0, -1, 1, 0);
5080 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
5081 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07005082}
5083
chaviw9eaa22c2020-07-01 16:21:27 -07005084TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005085 mWindow2->setWindowScale(0.5f, 0.5f);
5086
5087 // Touch Window 1
5088 std::vector<PointF> touchedPoints = {PointF{10, 10}};
5089 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07005090 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005091
5092 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07005093 touchedPoints.push_back(PointF{150, 150});
5094 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005095 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005096
chaviw9eaa22c2020-07-01 16:21:27 -07005097 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005098 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07005099 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005100
chaviw9eaa22c2020-07-01 16:21:27 -07005101 // Update the transform so rotation is set for Window 2
5102 mWindow2->setWindowTransform(0, -1, 1, 0);
5103 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005104 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005105}
5106
chaviw9eaa22c2020-07-01 16:21:27 -07005107TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005108 mWindow2->setWindowScale(0.5f, 0.5f);
5109
5110 // Touch Window 1
5111 std::vector<PointF> touchedPoints = {PointF{10, 10}};
5112 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07005113 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005114
5115 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07005116 touchedPoints.push_back(PointF{150, 150});
5117 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005118
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005119 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005120
5121 // Move both windows
5122 touchedPoints = {{20, 20}, {175, 175}};
5123 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
5124 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
5125
chaviw9eaa22c2020-07-01 16:21:27 -07005126 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005127
chaviw9eaa22c2020-07-01 16:21:27 -07005128 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005129 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07005130 expectedPoints.pop_back();
5131
5132 // Touch Window 2
5133 mWindow2->setWindowTransform(0, -1, 1, 0);
5134 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005135 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07005136
5137 // Move both windows
5138 touchedPoints = {{20, 20}, {175, 175}};
5139 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
5140 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
5141
5142 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005143}
5144
5145TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
5146 mWindow1->setWindowScale(0.5f, 0.5f);
5147
5148 // Touch Window 1
5149 std::vector<PointF> touchedPoints = {PointF{10, 10}};
5150 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07005151 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005152
5153 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07005154 touchedPoints.push_back(PointF{150, 150});
5155 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005156
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005157 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005158
5159 // Move both windows
5160 touchedPoints = {{20, 20}, {175, 175}};
5161 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
5162 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
5163
chaviw9eaa22c2020-07-01 16:21:27 -07005164 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00005165}
5166
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005167class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
5168 virtual void SetUp() override {
5169 InputDispatcherTest::SetUp();
5170
Chris Yea209fde2020-07-22 13:54:51 -07005171 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005172 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005173 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
5174 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005175 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05005176 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07005177 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005178
5179 // Set focused application.
5180 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
5181
5182 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005183 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005184 mWindow->consumeFocusEvent(true);
5185 }
5186
5187 virtual void TearDown() override {
5188 InputDispatcherTest::TearDown();
5189 mWindow.clear();
5190 }
5191
5192protected:
Chris Yea209fde2020-07-22 13:54:51 -07005193 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005194 sp<FakeWindowHandle> mWindow;
5195 static constexpr PointF WINDOW_LOCATION = {20, 20};
5196
5197 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005199 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5200 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005202 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5203 WINDOW_LOCATION));
5204 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005205
5206 sp<FakeWindowHandle> addSpyWindow() {
5207 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005208 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005209 spy->setTrustedOverlay(true);
5210 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08005211 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005212 spy->setDispatchingTimeout(30ms);
5213 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
5214 return spy;
5215 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005216};
5217
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005218// Send a tap and respond, which should not cause an ANR.
5219TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
5220 tapOnWindow();
5221 mWindow->consumeMotionDown();
5222 mWindow->consumeMotionUp();
5223 ASSERT_TRUE(mDispatcher->waitForIdle());
5224 mFakePolicy->assertNotifyAnrWasNotCalled();
5225}
5226
5227// Send a regular key and respond, which should not cause an ANR.
5228TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005230 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
5231 ASSERT_TRUE(mDispatcher->waitForIdle());
5232 mFakePolicy->assertNotifyAnrWasNotCalled();
5233}
5234
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05005235TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
5236 mWindow->setFocusable(false);
5237 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5238 mWindow->consumeFocusEvent(false);
5239
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005240 InputEventInjectionResult result =
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05005241 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005242 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
5243 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05005245 // Key will not go to window because we have no focused window.
5246 // The 'no focused window' ANR timer should start instead.
5247
5248 // Now, the focused application goes away.
5249 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
5250 // The key should get dropped and there should be no ANR.
5251
5252 ASSERT_TRUE(mDispatcher->waitForIdle());
5253 mFakePolicy->assertNotifyAnrWasNotCalled();
5254}
5255
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005256// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005257// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
5258// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005259TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005261 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5262 WINDOW_LOCATION));
5263
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005264 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
5265 ASSERT_TRUE(sequenceNum);
5266 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005267 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005268
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005269 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005270 mWindow->consumeMotionEvent(
5271 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005272 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005273 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005274}
5275
5276// Send a key to the app and have the app not respond right away.
5277TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
5278 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005280 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
5281 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005282 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005283 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07005284 ASSERT_TRUE(mDispatcher->waitForIdle());
5285}
5286
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005287// We have a focused application, but no focused window
5288TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07005289 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5291 mWindow->consumeFocusEvent(false);
5292
5293 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005295 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5296 WINDOW_LOCATION));
5297 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
5298 mDispatcher->waitForIdle();
5299 mFakePolicy->assertNotifyAnrWasNotCalled();
5300
5301 // Once a focused event arrives, we get an ANR for this application
5302 // We specify the injection timeout to be smaller than the application timeout, to ensure that
5303 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005304 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005305 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005306 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005307 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005308 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07005309 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005310 ASSERT_TRUE(mDispatcher->waitForIdle());
5311}
5312
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08005313/**
5314 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
5315 * there will not be an ANR.
5316 */
5317TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
5318 mWindow->setFocusable(false);
5319 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5320 mWindow->consumeFocusEvent(false);
5321
5322 KeyEvent event;
5323 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
5324 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
5325
5326 // Define a valid key down event that is stale (too old).
5327 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
5328 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
5329 AMETA_NONE, 1 /*repeatCount*/, eventTime, eventTime);
5330
5331 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
5332
5333 InputEventInjectionResult result =
Prabir Pradhan5735a322022-04-11 17:23:34 +00005334 mDispatcher->injectInputEvent(&event, {} /* targetUid */,
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08005335 InputEventInjectionSync::WAIT_FOR_RESULT,
5336 INJECT_EVENT_TIMEOUT, policyFlags);
5337 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
5338 << "Injection should fail because the event is stale";
5339
5340 ASSERT_TRUE(mDispatcher->waitForIdle());
5341 mFakePolicy->assertNotifyAnrWasNotCalled();
5342 mWindow->assertNoEvents();
5343}
5344
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005345// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005346// Make sure that we don't notify policy twice about the same ANR.
5347TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07005348 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005349 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5350 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005351
5352 // Once a focused event arrives, we get an ANR for this application
5353 // We specify the injection timeout to be smaller than the application timeout, to ensure that
5354 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005355 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005356 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005357 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005358 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07005359 const std::chrono::duration appTimeout =
5360 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
5361 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005362
Vishnu Naire4df8752022-09-08 09:17:55 -07005363 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005364 // ANR should not be raised again. It is up to policy to do that if it desires.
5365 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005366
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005367 // If we now get a focused window, the ANR should stop, but the policy handles that via
5368 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005369 ASSERT_TRUE(mDispatcher->waitForIdle());
5370}
5371
5372// We have a focused application, but no focused window
5373TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07005374 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5376 mWindow->consumeFocusEvent(false);
5377
5378 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005379 const InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005380 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005381 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
5382 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005383
Vishnu Naire4df8752022-09-08 09:17:55 -07005384 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
5385 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005386
5387 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005388 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005389 ASSERT_TRUE(mDispatcher->waitForIdle());
5390 mWindow->assertNoEvents();
5391}
5392
5393/**
5394 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
5395 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
5396 * If we process 1 of the events, but ANR on the second event with the same timestamp,
5397 * the ANR mechanism should still work.
5398 *
5399 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
5400 * DOWN event, while not responding on the second one.
5401 */
5402TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
5403 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
5404 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5405 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
5406 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
5407 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005408 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005409
5410 // Now send ACTION_UP, with identical timestamp
5411 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5412 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
5413 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
5414 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005415 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005416
5417 // We have now sent down and up. Let's consume first event and then ANR on the second.
5418 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5419 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005420 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005421}
5422
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005423// A spy window can receive an ANR
5424TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
5425 sp<FakeWindowHandle> spy = addSpyWindow();
5426
5427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5428 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5429 WINDOW_LOCATION));
5430 mWindow->consumeMotionDown();
5431
5432 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
5433 ASSERT_TRUE(sequenceNum);
5434 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005435 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005436
5437 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005438 spy->consumeMotionEvent(
5439 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005440 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005441 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005442}
5443
5444// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005445// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005446TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
5447 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005448
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5450 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005451 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005453
5454 // Stuck on the ACTION_UP
5455 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005456 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005457
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005458 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005459 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005460 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5461 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005462
5463 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
5464 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005465 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005466 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005467 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005468}
5469
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005470// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005471// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005472TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
5473 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005474
5475 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005476 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5477 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005478
5479 mWindow->consumeMotionDown();
5480 // Stuck on the ACTION_UP
5481 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005482 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005483
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005484 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005485 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005486 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5487 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005488
5489 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
5490 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005491 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005492 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005493 spy->assertNoEvents();
5494}
5495
5496TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
5497 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
5498
5499 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5500
5501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5502 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5503 WINDOW_LOCATION));
5504
5505 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5506 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
5507 ASSERT_TRUE(consumeSeq);
5508
Prabir Pradhanedd96402022-02-15 01:46:16 -08005509 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005510
5511 monitor.finishEvent(*consumeSeq);
5512 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5513
5514 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005515 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005516}
5517
5518// If a window is unresponsive, then you get anr. if the window later catches up and starts to
5519// process events, you don't get an anr. When the window later becomes unresponsive again, you
5520// get an ANR again.
5521// 1. tap -> block on ACTION_UP -> receive ANR
5522// 2. consume all pending events (= queue becomes healthy again)
5523// 3. tap again -> block on ACTION_UP again -> receive ANR second time
5524TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
5525 tapOnWindow();
5526
5527 mWindow->consumeMotionDown();
5528 // Block on ACTION_UP
5529 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005530 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005531 mWindow->consumeMotionUp(); // Now the connection should be healthy again
5532 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005533 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005534 mWindow->assertNoEvents();
5535
5536 tapOnWindow();
5537 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005538 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005539 mWindow->consumeMotionUp();
5540
5541 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005542 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005543 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005544 mWindow->assertNoEvents();
5545}
5546
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005547// If a connection remains unresponsive for a while, make sure policy is only notified once about
5548// it.
5549TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005551 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5552 WINDOW_LOCATION));
5553
5554 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005555 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005556 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005557 // 'notifyConnectionUnresponsive' should only be called once per connection
5558 mFakePolicy->assertNotifyAnrWasNotCalled();
5559 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005560 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005561 mWindow->consumeMotionEvent(
5562 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005563 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005564 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08005565 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005566 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005567}
5568
5569/**
5570 * If a window is processing a motion event, and then a key event comes in, the key event should
5571 * not to to the focused window until the motion is processed.
5572 *
5573 * Warning!!!
5574 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
5575 * and the injection timeout that we specify when injecting the key.
5576 * We must have the injection timeout (10ms) be smaller than
5577 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
5578 *
5579 * If that value changes, this test should also change.
5580 */
5581TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
5582 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
5583 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5584
5585 tapOnWindow();
5586 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
5587 ASSERT_TRUE(downSequenceNum);
5588 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
5589 ASSERT_TRUE(upSequenceNum);
5590 // Don't finish the events yet, and send a key
5591 // Injection will "succeed" because we will eventually give up and send the key to the focused
5592 // window even if motions are still being processed. But because the injection timeout is short,
5593 // we will receive INJECTION_TIMED_OUT as the result.
5594
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005595 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005596 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005597 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
5598 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005599 // Key will not be sent to the window, yet, because the window is still processing events
5600 // and the key remains pending, waiting for the touch events to be processed
5601 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
5602 ASSERT_FALSE(keySequenceNum);
5603
5604 std::this_thread::sleep_for(500ms);
5605 // if we wait long enough though, dispatcher will give up, and still send the key
5606 // to the focused window, even though we have not yet finished the motion event
5607 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5608 mWindow->finishEvent(*downSequenceNum);
5609 mWindow->finishEvent(*upSequenceNum);
5610}
5611
5612/**
5613 * If a window is processing a motion event, and then a key event comes in, the key event should
5614 * not go to the focused window until the motion is processed.
5615 * If then a new motion comes in, then the pending key event should be going to the currently
5616 * focused window right away.
5617 */
5618TEST_F(InputDispatcherSingleWindowAnr,
5619 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
5620 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
5621 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5622
5623 tapOnWindow();
5624 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
5625 ASSERT_TRUE(downSequenceNum);
5626 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
5627 ASSERT_TRUE(upSequenceNum);
5628 // Don't finish the events yet, and send a key
5629 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005631 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005632 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005633 // At this point, key is still pending, and should not be sent to the application yet.
5634 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
5635 ASSERT_FALSE(keySequenceNum);
5636
5637 // Now tap down again. It should cause the pending key to go to the focused window right away.
5638 tapOnWindow();
5639 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
5640 // the other events yet. We can finish events in any order.
5641 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
5642 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
5643 mWindow->consumeMotionDown();
5644 mWindow->consumeMotionUp();
5645 mWindow->assertNoEvents();
5646}
5647
5648class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
5649 virtual void SetUp() override {
5650 InputDispatcherTest::SetUp();
5651
Chris Yea209fde2020-07-22 13:54:51 -07005652 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005653 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005654 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
5655 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005656 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005657 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005658 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005659
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005660 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
5661 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05005662 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005663 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005664
5665 // Set focused application.
5666 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07005667 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005668
5669 // Expect one focus window exist in display.
5670 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005671 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005672 mFocusedWindow->consumeFocusEvent(true);
5673 }
5674
5675 virtual void TearDown() override {
5676 InputDispatcherTest::TearDown();
5677
5678 mUnfocusedWindow.clear();
5679 mFocusedWindow.clear();
5680 }
5681
5682protected:
Chris Yea209fde2020-07-22 13:54:51 -07005683 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005684 sp<FakeWindowHandle> mUnfocusedWindow;
5685 sp<FakeWindowHandle> mFocusedWindow;
5686 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
5687 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
5688 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
5689
5690 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
5691
5692 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
5693
5694private:
5695 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005697 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5698 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005700 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5701 location));
5702 }
5703};
5704
5705// If we have 2 windows that are both unresponsive, the one with the shortest timeout
5706// should be ANR'd first.
5707TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005709 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5710 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005711 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005712 mFocusedWindow->consumeMotionDown();
5713 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5714 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5715 // We consumed all events, so no ANR
5716 ASSERT_TRUE(mDispatcher->waitForIdle());
5717 mFakePolicy->assertNotifyAnrWasNotCalled();
5718
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005720 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5721 FOCUSED_WINDOW_LOCATION));
5722 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
5723 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005724
5725 const std::chrono::duration timeout =
5726 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005727 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005728 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
5729 // sequence to make it consistent
5730 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005731 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005732 mFocusedWindow->consumeMotionDown();
5733 // This cancel is generated because the connection was unresponsive
5734 mFocusedWindow->consumeMotionCancel();
5735 mFocusedWindow->assertNoEvents();
5736 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005737 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005738 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5739 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005740 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005741}
5742
5743// If we have 2 windows with identical timeouts that are both unresponsive,
5744// it doesn't matter which order they should have ANR.
5745// But we should receive ANR for both.
5746TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
5747 // Set the timeout for unfocused window to match the focused window
5748 mUnfocusedWindow->setDispatchingTimeout(10ms);
5749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
5750
5751 tapOnFocusedWindow();
5752 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08005753 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
5754 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
5755 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005756
5757 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005758 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
5759 mFocusedWindow->getToken() == anrConnectionToken2);
5760 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
5761 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005762
5763 ASSERT_TRUE(mDispatcher->waitForIdle());
5764 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005765
5766 mFocusedWindow->consumeMotionDown();
5767 mFocusedWindow->consumeMotionUp();
5768 mUnfocusedWindow->consumeMotionOutside();
5769
Prabir Pradhanedd96402022-02-15 01:46:16 -08005770 sp<IBinder> responsiveToken1, responsiveToken2;
5771 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
5772 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005773
5774 // Both applications should be marked as responsive, in any order
5775 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
5776 mFocusedWindow->getToken() == responsiveToken2);
5777 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
5778 mUnfocusedWindow->getToken() == responsiveToken2);
5779 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005780}
5781
5782// If a window is already not responding, the second tap on the same window should be ignored.
5783// We should also log an error to account for the dropped event (not tested here).
5784// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
5785TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
5786 tapOnFocusedWindow();
5787 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5788 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5789 // Receive the events, but don't respond
5790 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
5791 ASSERT_TRUE(downEventSequenceNum);
5792 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
5793 ASSERT_TRUE(upEventSequenceNum);
5794 const std::chrono::duration timeout =
5795 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005796 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005797
5798 // Tap once again
5799 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005800 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005801 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5802 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005803 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005804 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5805 FOCUSED_WINDOW_LOCATION));
5806 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
5807 // valid touch target
5808 mUnfocusedWindow->assertNoEvents();
5809
5810 // Consume the first tap
5811 mFocusedWindow->finishEvent(*downEventSequenceNum);
5812 mFocusedWindow->finishEvent(*upEventSequenceNum);
5813 ASSERT_TRUE(mDispatcher->waitForIdle());
5814 // The second tap did not go to the focused window
5815 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005816 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08005817 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5818 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005819 mFakePolicy->assertNotifyAnrWasNotCalled();
5820}
5821
5822// If you tap outside of all windows, there will not be ANR
5823TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005824 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005825 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5826 LOCATION_OUTSIDE_ALL_WINDOWS));
5827 ASSERT_TRUE(mDispatcher->waitForIdle());
5828 mFakePolicy->assertNotifyAnrWasNotCalled();
5829}
5830
5831// Since the focused window is paused, tapping on it should not produce any events
5832TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
5833 mFocusedWindow->setPaused(true);
5834 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
5835
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005836 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005837 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5838 FOCUSED_WINDOW_LOCATION));
5839
5840 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
5841 ASSERT_TRUE(mDispatcher->waitForIdle());
5842 // Should not ANR because the window is paused, and touches shouldn't go to it
5843 mFakePolicy->assertNotifyAnrWasNotCalled();
5844
5845 mFocusedWindow->assertNoEvents();
5846 mUnfocusedWindow->assertNoEvents();
5847}
5848
5849/**
5850 * If a window is processing a motion event, and then a key event comes in, the key event should
5851 * not to to the focused window until the motion is processed.
5852 * If a different window becomes focused at this time, the key should go to that window instead.
5853 *
5854 * Warning!!!
5855 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
5856 * and the injection timeout that we specify when injecting the key.
5857 * We must have the injection timeout (10ms) be smaller than
5858 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
5859 *
5860 * If that value changes, this test should also change.
5861 */
5862TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
5863 // Set a long ANR timeout to prevent it from triggering
5864 mFocusedWindow->setDispatchingTimeout(2s);
5865 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5866
5867 tapOnUnfocusedWindow();
5868 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
5869 ASSERT_TRUE(downSequenceNum);
5870 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
5871 ASSERT_TRUE(upSequenceNum);
5872 // Don't finish the events yet, and send a key
5873 // Injection will succeed because we will eventually give up and send the key to the focused
5874 // window even if motions are still being processed.
5875
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005876 InputEventInjectionResult result =
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005877 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005878 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/);
5879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005880 // Key will not be sent to the window, yet, because the window is still processing events
5881 // and the key remains pending, waiting for the touch events to be processed
5882 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
5883 ASSERT_FALSE(keySequenceNum);
5884
5885 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07005886 mFocusedWindow->setFocusable(false);
5887 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005889 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005890
5891 // Focus events should precede the key events
5892 mUnfocusedWindow->consumeFocusEvent(true);
5893 mFocusedWindow->consumeFocusEvent(false);
5894
5895 // Finish the tap events, which should unblock dispatcher
5896 mUnfocusedWindow->finishEvent(*downSequenceNum);
5897 mUnfocusedWindow->finishEvent(*upSequenceNum);
5898
5899 // Now that all queues are cleared and no backlog in the connections, the key event
5900 // can finally go to the newly focused "mUnfocusedWindow".
5901 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5902 mFocusedWindow->assertNoEvents();
5903 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005904 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005905}
5906
5907// When the touch stream is split across 2 windows, and one of them does not respond,
5908// then ANR should be raised and the touch should be canceled for the unresponsive window.
5909// The other window should not be affected by that.
5910TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
5911 // Touch Window 1
5912 NotifyMotionArgs motionArgs =
5913 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5914 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
5915 mDispatcher->notifyMotion(&motionArgs);
5916 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
5917 ADISPLAY_ID_DEFAULT, 0 /*flags*/);
5918
5919 // Touch Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005920 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5921 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005922 mDispatcher->notifyMotion(&motionArgs);
5923
5924 const std::chrono::duration timeout =
5925 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08005926 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005927
5928 mUnfocusedWindow->consumeMotionDown();
5929 mFocusedWindow->consumeMotionDown();
5930 // Focused window may or may not receive ACTION_MOVE
5931 // But it should definitely receive ACTION_CANCEL due to the ANR
5932 InputEvent* event;
5933 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
5934 ASSERT_TRUE(moveOrCancelSequenceNum);
5935 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
5936 ASSERT_NE(nullptr, event);
5937 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
5938 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
5939 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
5940 mFocusedWindow->consumeMotionCancel();
5941 } else {
5942 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
5943 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005944 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08005945 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
5946 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005947
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005948 mUnfocusedWindow->assertNoEvents();
5949 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05005950 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005951}
5952
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005953/**
5954 * If we have no focused window, and a key comes in, we start the ANR timer.
5955 * The focused application should add a focused window before the timer runs out to prevent ANR.
5956 *
5957 * If the user touches another application during this time, the key should be dropped.
5958 * Next, if a new focused window comes in, without toggling the focused application,
5959 * then no ANR should occur.
5960 *
5961 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
5962 * but in some cases the policy may not update the focused application.
5963 */
5964TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
5965 std::shared_ptr<FakeApplicationHandle> focusedApplication =
5966 std::make_shared<FakeApplicationHandle>();
5967 focusedApplication->setDispatchingTimeout(60ms);
5968 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
5969 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
5970 mFocusedWindow->setFocusable(false);
5971
5972 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
5973 mFocusedWindow->consumeFocusEvent(false);
5974
5975 // Send a key. The ANR timer should start because there is no focused window.
5976 // 'focusedApplication' will get blamed if this timer completes.
5977 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005978 InputEventInjectionResult result =
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005979 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /*repeatCount*/, ADISPLAY_ID_DEFAULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005980 InputEventInjectionSync::NONE, 10ms /*injectionTimeout*/,
5981 false /* allowKeyRepeat */);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05005983
5984 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
5985 // then the injected touches won't cause the focused event to get dropped.
5986 // The dispatcher only checks for whether the queue should be pruned upon queueing.
5987 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
5988 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
5989 // For this test, it means that the key would get delivered to the window once it becomes
5990 // focused.
5991 std::this_thread::sleep_for(10ms);
5992
5993 // Touch unfocused window. This should force the pending key to get dropped.
5994 NotifyMotionArgs motionArgs =
5995 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5996 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
5997 mDispatcher->notifyMotion(&motionArgs);
5998
5999 // We do not consume the motion right away, because that would require dispatcher to first
6000 // process (== drop) the key event, and by that time, ANR will be raised.
6001 // Set the focused window first.
6002 mFocusedWindow->setFocusable(true);
6003 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6004 setFocusedWindow(mFocusedWindow);
6005 mFocusedWindow->consumeFocusEvent(true);
6006 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
6007 // to another application. This could be a bug / behaviour in the policy.
6008
6009 mUnfocusedWindow->consumeMotionDown();
6010
6011 ASSERT_TRUE(mDispatcher->waitForIdle());
6012 // Should not ANR because we actually have a focused window. It was just added too slowly.
6013 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
6014}
6015
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006016// These tests ensure we cannot send touch events to a window that's positioned behind a window
6017// that has feature NO_INPUT_CHANNEL.
6018// Layout:
6019// Top (closest to user)
6020// mNoInputWindow (above all windows)
6021// mBottomWindow
6022// Bottom (furthest from user)
6023class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
6024 virtual void SetUp() override {
6025 InputDispatcherTest::SetUp();
6026
6027 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006028 mNoInputWindow =
6029 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
6030 "Window without input channel", ADISPLAY_ID_DEFAULT,
6031 std::make_optional<sp<IBinder>>(nullptr) /*token*/);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006032 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006033 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
6034 // It's perfectly valid for this window to not have an associated input channel
6035
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006036 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
6037 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006038 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
6039
6040 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
6041 }
6042
6043protected:
6044 std::shared_ptr<FakeApplicationHandle> mApplication;
6045 sp<FakeWindowHandle> mNoInputWindow;
6046 sp<FakeWindowHandle> mBottomWindow;
6047};
6048
6049TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
6050 PointF touchedPoint = {10, 10};
6051
6052 NotifyMotionArgs motionArgs =
6053 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6054 ADISPLAY_ID_DEFAULT, {touchedPoint});
6055 mDispatcher->notifyMotion(&motionArgs);
6056
6057 mNoInputWindow->assertNoEvents();
6058 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
6059 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
6060 // and therefore should prevent mBottomWindow from receiving touches
6061 mBottomWindow->assertNoEvents();
6062}
6063
6064/**
6065 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
6066 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
6067 */
6068TEST_F(InputDispatcherMultiWindowOcclusionTests,
6069 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006070 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
6071 "Window with input channel and NO_INPUT_CHANNEL",
6072 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006073
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006074 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006075 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
6076 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
6077
6078 PointF touchedPoint = {10, 10};
6079
6080 NotifyMotionArgs motionArgs =
6081 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6082 ADISPLAY_ID_DEFAULT, {touchedPoint});
6083 mDispatcher->notifyMotion(&motionArgs);
6084
6085 mNoInputWindow->assertNoEvents();
6086 mBottomWindow->assertNoEvents();
6087}
6088
Vishnu Nair958da932020-08-21 17:12:37 -07006089class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
6090protected:
6091 std::shared_ptr<FakeApplicationHandle> mApp;
6092 sp<FakeWindowHandle> mWindow;
6093 sp<FakeWindowHandle> mMirror;
6094
6095 virtual void SetUp() override {
6096 InputDispatcherTest::SetUp();
6097 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006098 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
6099 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
6100 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07006101 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
6102 mWindow->setFocusable(true);
6103 mMirror->setFocusable(true);
6104 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
6105 }
6106};
6107
6108TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
6109 // Request focus on a mirrored window
6110 setFocusedWindow(mMirror);
6111
6112 // window gets focused
6113 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6115 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006116 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6117}
6118
6119// A focused & mirrored window remains focused only if the window and its mirror are both
6120// focusable.
6121TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
6122 setFocusedWindow(mMirror);
6123
6124 // window gets focused
6125 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6127 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006128 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
6130 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006131 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
6132
6133 mMirror->setFocusable(false);
6134 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
6135
6136 // window loses focus since one of the windows associated with the token in not focusable
6137 mWindow->consumeFocusEvent(false);
6138
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006139 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
6140 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07006141 mWindow->assertNoEvents();
6142}
6143
6144// A focused & mirrored window remains focused until the window and its mirror both become
6145// invisible.
6146TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
6147 setFocusedWindow(mMirror);
6148
6149 // window gets focused
6150 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6152 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006153 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
6155 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006156 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
6157
6158 mMirror->setVisible(false);
6159 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
6160
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6162 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006163 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
6165 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006166 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
6167
6168 mWindow->setVisible(false);
6169 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
6170
6171 // window loses focus only after all windows associated with the token become invisible.
6172 mWindow->consumeFocusEvent(false);
6173
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006174 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
6175 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07006176 mWindow->assertNoEvents();
6177}
6178
6179// A focused & mirrored window remains focused until both windows are removed.
6180TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
6181 setFocusedWindow(mMirror);
6182
6183 // window gets focused
6184 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6186 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006187 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
6189 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006190 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
6191
6192 // single window is removed but the window token remains focused
6193 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
6194
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6196 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006197 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
6199 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006200 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
6201
6202 // Both windows are removed
6203 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
6204 mWindow->consumeFocusEvent(false);
6205
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006206 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
6207 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07006208 mWindow->assertNoEvents();
6209}
6210
6211// Focus request can be pending until one window becomes visible.
6212TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
6213 // Request focus on an invisible mirror.
6214 mWindow->setVisible(false);
6215 mMirror->setVisible(false);
6216 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
6217 setFocusedWindow(mMirror);
6218
6219 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Vishnu Nair958da932020-08-21 17:12:37 -07006221 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006222 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006223
6224 mMirror->setVisible(true);
6225 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
6226
6227 // window gets focused
6228 mWindow->consumeFocusEvent(true);
6229 // window gets the pending key event
6230 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6231}
Prabir Pradhan99987712020-11-10 18:43:05 -08006232
6233class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
6234protected:
6235 std::shared_ptr<FakeApplicationHandle> mApp;
6236 sp<FakeWindowHandle> mWindow;
6237 sp<FakeWindowHandle> mSecondWindow;
6238
6239 void SetUp() override {
6240 InputDispatcherTest::SetUp();
6241 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006242 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08006243 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006244 mSecondWindow =
6245 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08006246 mSecondWindow->setFocusable(true);
6247
6248 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
6249 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
6250
6251 setFocusedWindow(mWindow);
6252 mWindow->consumeFocusEvent(true);
6253 }
6254
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006255 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
6256 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08006257 mDispatcher->notifyPointerCaptureChanged(&args);
6258 }
6259
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006260 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
6261 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08006262 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006263 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
6264 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08006265 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006266 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08006267 }
6268};
6269
6270TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
6271 // Ensure that capture cannot be obtained for unfocused windows.
6272 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
6273 mFakePolicy->assertSetPointerCaptureNotCalled();
6274 mSecondWindow->assertNoEvents();
6275
6276 // Ensure that capture can be enabled from the focus window.
6277 requestAndVerifyPointerCapture(mWindow, true);
6278
6279 // Ensure that capture cannot be disabled from a window that does not have capture.
6280 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
6281 mFakePolicy->assertSetPointerCaptureNotCalled();
6282
6283 // Ensure that capture can be disabled from the window with capture.
6284 requestAndVerifyPointerCapture(mWindow, false);
6285}
6286
6287TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006288 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08006289
6290 setFocusedWindow(mSecondWindow);
6291
6292 // Ensure that the capture disabled event was sent first.
6293 mWindow->consumeCaptureEvent(false);
6294 mWindow->consumeFocusEvent(false);
6295 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006296 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08006297
6298 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006299 notifyPointerCaptureChanged({});
6300 notifyPointerCaptureChanged(request);
6301 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08006302 mWindow->assertNoEvents();
6303 mSecondWindow->assertNoEvents();
6304 mFakePolicy->assertSetPointerCaptureNotCalled();
6305}
6306
6307TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006308 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08006309
6310 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006311 notifyPointerCaptureChanged({});
6312 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08006313
6314 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006315 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08006316 mWindow->consumeCaptureEvent(false);
6317 mWindow->assertNoEvents();
6318}
6319
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006320TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
6321 requestAndVerifyPointerCapture(mWindow, true);
6322
6323 // The first window loses focus.
6324 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006325 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006326 mWindow->consumeCaptureEvent(false);
6327
6328 // Request Pointer Capture from the second window before the notification from InputReader
6329 // arrives.
6330 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006331 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006332
6333 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006334 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006335
6336 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006337 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08006338
6339 mSecondWindow->consumeFocusEvent(true);
6340 mSecondWindow->consumeCaptureEvent(true);
6341}
6342
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00006343TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
6344 // App repeatedly enables and disables capture.
6345 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6346 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6347 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
6348 mFakePolicy->assertSetPointerCaptureCalled(false);
6349 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6350 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6351
6352 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
6353 // first request is now stale, this should do nothing.
6354 notifyPointerCaptureChanged(firstRequest);
6355 mWindow->assertNoEvents();
6356
6357 // InputReader notifies that the second request was enabled.
6358 notifyPointerCaptureChanged(secondRequest);
6359 mWindow->consumeCaptureEvent(true);
6360}
6361
Prabir Pradhan7092e262022-05-03 16:51:09 +00006362TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
6363 requestAndVerifyPointerCapture(mWindow, true);
6364
6365 // App toggles pointer capture off and on.
6366 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
6367 mFakePolicy->assertSetPointerCaptureCalled(false);
6368
6369 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
6370 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
6371
6372 // InputReader notifies that the latest "enable" request was processed, while skipping over the
6373 // preceding "disable" request.
6374 notifyPointerCaptureChanged(enableRequest);
6375
6376 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
6377 // any notifications.
6378 mWindow->assertNoEvents();
6379}
6380
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006381class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
6382protected:
6383 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00006384
6385 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
6386 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
6387
6388 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
6389 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
6390
6391 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
6392 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
6393 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
6394 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
6395 MAXIMUM_OBSCURING_OPACITY);
6396
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006397 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006398 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006399 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006400
6401 sp<FakeWindowHandle> mTouchWindow;
6402
6403 virtual void SetUp() override {
6404 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006405 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006406 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
6407 }
6408
6409 virtual void TearDown() override {
6410 InputDispatcherTest::TearDown();
6411 mTouchWindow.clear();
6412 }
6413
chaviw3277faf2021-05-19 16:45:23 -05006414 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
6415 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006416 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006417 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006418 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006419 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006420 return window;
6421 }
6422
6423 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
6424 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
6425 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006426 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006427 // Generate an arbitrary PID based on the UID
6428 window->setOwnerInfo(1777 + (uid % 10000), uid);
6429 return window;
6430 }
6431
6432 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
6433 NotifyMotionArgs args =
6434 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6435 ADISPLAY_ID_DEFAULT, points);
6436 mDispatcher->notifyMotion(&args);
6437 }
6438};
6439
6440TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006441 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006442 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006443 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006444
6445 touch();
6446
6447 mTouchWindow->assertNoEvents();
6448}
6449
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006450TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00006451 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
6452 const sp<FakeWindowHandle>& w =
6453 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
6454 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6455
6456 touch();
6457
6458 mTouchWindow->assertNoEvents();
6459}
6460
6461TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006462 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
6463 const sp<FakeWindowHandle>& w =
6464 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
6465 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6466
6467 touch();
6468
6469 w->assertNoEvents();
6470}
6471
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006472TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006473 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
6474 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006475
6476 touch();
6477
6478 mTouchWindow->consumeAnyMotionDown();
6479}
6480
6481TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006482 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006483 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006484 w->setFrame(Rect(0, 0, 50, 50));
6485 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006486
6487 touch({PointF{100, 100}});
6488
6489 mTouchWindow->consumeAnyMotionDown();
6490}
6491
6492TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006493 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006494 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006495 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6496
6497 touch();
6498
6499 mTouchWindow->consumeAnyMotionDown();
6500}
6501
6502TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
6503 const sp<FakeWindowHandle>& w =
6504 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
6505 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006506
6507 touch();
6508
6509 mTouchWindow->consumeAnyMotionDown();
6510}
6511
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006512TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
6513 const sp<FakeWindowHandle>& w =
6514 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
6515 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6516
6517 touch();
6518
6519 w->assertNoEvents();
6520}
6521
6522/**
6523 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
6524 * inside) while letting them pass-through. Note that even though touch passes through the occluding
6525 * window, the occluding window will still receive ACTION_OUTSIDE event.
6526 */
6527TEST_F(InputDispatcherUntrustedTouchesTest,
6528 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
6529 const sp<FakeWindowHandle>& w =
6530 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006531 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006532 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6533
6534 touch();
6535
6536 w->consumeMotionOutside();
6537}
6538
6539TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
6540 const sp<FakeWindowHandle>& w =
6541 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006542 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006543 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6544
6545 touch();
6546
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08006547 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00006548}
6549
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006550TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006551 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006552 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6553 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006554 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6555
6556 touch();
6557
6558 mTouchWindow->consumeAnyMotionDown();
6559}
6560
6561TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
6562 const sp<FakeWindowHandle>& w =
6563 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6564 MAXIMUM_OBSCURING_OPACITY);
6565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006566
6567 touch();
6568
6569 mTouchWindow->consumeAnyMotionDown();
6570}
6571
6572TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006573 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006574 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6575 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006576 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6577
6578 touch();
6579
6580 mTouchWindow->assertNoEvents();
6581}
6582
6583TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
6584 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
6585 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006586 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
6587 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006588 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006589 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
6590 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6592
6593 touch();
6594
6595 mTouchWindow->assertNoEvents();
6596}
6597
6598TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
6599 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
6600 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006601 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
6602 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006603 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006604 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
6605 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006606 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6607
6608 touch();
6609
6610 mTouchWindow->consumeAnyMotionDown();
6611}
6612
6613TEST_F(InputDispatcherUntrustedTouchesTest,
6614 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
6615 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006616 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6617 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006618 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006619 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6620 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006621 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
6622
6623 touch();
6624
6625 mTouchWindow->consumeAnyMotionDown();
6626}
6627
6628TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
6629 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006630 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6631 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006632 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006633 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6634 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00006635 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00006636
6637 touch();
6638
6639 mTouchWindow->assertNoEvents();
6640}
6641
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006642TEST_F(InputDispatcherUntrustedTouchesTest,
6643 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
6644 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006645 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6646 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006647 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006648 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6649 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
6651
6652 touch();
6653
6654 mTouchWindow->assertNoEvents();
6655}
6656
6657TEST_F(InputDispatcherUntrustedTouchesTest,
6658 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
6659 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006660 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6661 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006662 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006663 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6664 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006665 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
6666
6667 touch();
6668
6669 mTouchWindow->consumeAnyMotionDown();
6670}
6671
6672TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
6673 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006674 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
6675 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00006676 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6677
6678 touch();
6679
6680 mTouchWindow->consumeAnyMotionDown();
6681}
6682
6683TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
6684 const sp<FakeWindowHandle>& w =
6685 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
6686 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6687
6688 touch();
6689
6690 mTouchWindow->consumeAnyMotionDown();
6691}
6692
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00006693TEST_F(InputDispatcherUntrustedTouchesTest,
6694 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
6695 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
6696 const sp<FakeWindowHandle>& w =
6697 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
6698 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6699
6700 touch();
6701
6702 mTouchWindow->assertNoEvents();
6703}
6704
6705TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
6706 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
6707 const sp<FakeWindowHandle>& w =
6708 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
6709 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6710
6711 touch();
6712
6713 mTouchWindow->consumeAnyMotionDown();
6714}
6715
6716TEST_F(InputDispatcherUntrustedTouchesTest,
6717 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
6718 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
6719 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00006720 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6721 OPACITY_ABOVE_THRESHOLD);
6722 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6723
6724 touch();
6725
6726 mTouchWindow->consumeAnyMotionDown();
6727}
6728
6729TEST_F(InputDispatcherUntrustedTouchesTest,
6730 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
6731 const sp<FakeWindowHandle>& w1 =
6732 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
6733 OPACITY_BELOW_THRESHOLD);
6734 const sp<FakeWindowHandle>& w2 =
6735 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
6736 OPACITY_BELOW_THRESHOLD);
6737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
6738
6739 touch();
6740
6741 mTouchWindow->assertNoEvents();
6742}
6743
6744/**
6745 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
6746 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
6747 * (which alone would result in allowing touches) does not affect the blocking behavior.
6748 */
6749TEST_F(InputDispatcherUntrustedTouchesTest,
6750 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
6751 const sp<FakeWindowHandle>& wB =
6752 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
6753 OPACITY_BELOW_THRESHOLD);
6754 const sp<FakeWindowHandle>& wC =
6755 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
6756 OPACITY_BELOW_THRESHOLD);
6757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
6758
6759 touch();
6760
6761 mTouchWindow->assertNoEvents();
6762}
6763
6764/**
6765 * This test is testing that a window from a different UID but with same application token doesn't
6766 * block the touch. Apps can share the application token for close UI collaboration for example.
6767 */
6768TEST_F(InputDispatcherUntrustedTouchesTest,
6769 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
6770 const sp<FakeWindowHandle>& w =
6771 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
6772 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00006773 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
6774
6775 touch();
6776
6777 mTouchWindow->consumeAnyMotionDown();
6778}
6779
arthurhungb89ccb02020-12-30 16:19:01 +08006780class InputDispatcherDragTests : public InputDispatcherTest {
6781protected:
6782 std::shared_ptr<FakeApplicationHandle> mApp;
6783 sp<FakeWindowHandle> mWindow;
6784 sp<FakeWindowHandle> mSecondWindow;
6785 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006786 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006787 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
6788 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08006789
6790 void SetUp() override {
6791 InputDispatcherTest::SetUp();
6792 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006793 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08006794 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08006795
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006796 mSecondWindow =
6797 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08006798 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08006799
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006800 mSpyWindow =
6801 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006802 mSpyWindow->setSpy(true);
6803 mSpyWindow->setTrustedOverlay(true);
6804 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
6805
arthurhungb89ccb02020-12-30 16:19:01 +08006806 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006807 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08006808 }
6809
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006810 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
6811 switch (fromSource) {
6812 case AINPUT_SOURCE_TOUCHSCREEN:
6813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6814 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6815 ADISPLAY_ID_DEFAULT, {50, 50}))
6816 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6817 break;
6818 case AINPUT_SOURCE_STYLUS:
6819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6820 injectMotionEvent(
6821 mDispatcher,
6822 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
6823 AINPUT_SOURCE_STYLUS)
6824 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
6825 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6826 .x(50)
6827 .y(50))
6828 .build()));
6829 break;
6830 case AINPUT_SOURCE_MOUSE:
6831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6832 injectMotionEvent(
6833 mDispatcher,
6834 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6835 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
6836 .pointer(PointerBuilder(MOUSE_POINTER_ID,
6837 AMOTION_EVENT_TOOL_TYPE_MOUSE)
6838 .x(50)
6839 .y(50))
6840 .build()));
6841 break;
6842 default:
6843 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
6844 }
arthurhungb89ccb02020-12-30 16:19:01 +08006845
6846 // Window should receive motion event.
6847 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006848 // Spy window should also receive motion event
6849 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00006850 }
6851
6852 // Start performing drag, we will create a drag window and transfer touch to it.
6853 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
6854 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006855 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00006856 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006857 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00006858 }
arthurhungb89ccb02020-12-30 16:19:01 +08006859
6860 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006861 mDragWindow =
6862 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006863 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08006864 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006865 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08006866
6867 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00006868 bool transferred =
6869 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
6870 true /* isDragDrop */);
6871 if (transferred) {
6872 mWindow->consumeMotionCancel();
6873 mDragWindow->consumeMotionDown();
6874 }
6875 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08006876 }
6877};
6878
6879TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006880 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08006881
6882 // Move on window.
6883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6884 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6885 ADISPLAY_ID_DEFAULT, {50, 50}))
6886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6887 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6888 mWindow->consumeDragEvent(false, 50, 50);
6889 mSecondWindow->assertNoEvents();
6890
6891 // Move to another window.
6892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6893 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6894 ADISPLAY_ID_DEFAULT, {150, 50}))
6895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6896 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6897 mWindow->consumeDragEvent(true, 150, 50);
6898 mSecondWindow->consumeDragEvent(false, 50, 50);
6899
6900 // Move back to original window.
6901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6902 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6903 ADISPLAY_ID_DEFAULT, {50, 50}))
6904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6905 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6906 mWindow->consumeDragEvent(false, 50, 50);
6907 mSecondWindow->consumeDragEvent(true, -50, 50);
6908
6909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6910 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
6911 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6912 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6913 mWindow->assertNoEvents();
6914 mSecondWindow->assertNoEvents();
6915}
6916
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006917TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006918 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00006919
6920 // No cancel event after drag start
6921 mSpyWindow->assertNoEvents();
6922
6923 const MotionEvent secondFingerDownEvent =
6924 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6925 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
6926 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
6927 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60))
6928 .build();
6929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6930 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
6931 InputEventInjectionSync::WAIT_FOR_RESULT))
6932 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6933
6934 // Receives cancel for first pointer after next pointer down
6935 mSpyWindow->consumeMotionCancel();
6936 mSpyWindow->consumeMotionDown();
6937
6938 mSpyWindow->assertNoEvents();
6939}
6940
arthurhungf452d0b2021-01-06 00:19:52 +08006941TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006942 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08006943
6944 // Move on window.
6945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6946 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6947 ADISPLAY_ID_DEFAULT, {50, 50}))
6948 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6949 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6950 mWindow->consumeDragEvent(false, 50, 50);
6951 mSecondWindow->assertNoEvents();
6952
6953 // Move to another window.
6954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6955 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6956 ADISPLAY_ID_DEFAULT, {150, 50}))
6957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6958 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6959 mWindow->consumeDragEvent(true, 150, 50);
6960 mSecondWindow->consumeDragEvent(false, 50, 50);
6961
6962 // drop to another window.
6963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6964 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6965 {150, 50}))
6966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6967 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6968 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
6969 mWindow->assertNoEvents();
6970 mSecondWindow->assertNoEvents();
6971}
6972
arthurhung6d4bed92021-03-17 11:59:33 +08006973TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00006974 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08006975
6976 // Move on window and keep button pressed.
6977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6978 injectMotionEvent(mDispatcher,
6979 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
6980 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
6981 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6982 .x(50)
6983 .y(50))
6984 .build()))
6985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6986 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
6987 mWindow->consumeDragEvent(false, 50, 50);
6988 mSecondWindow->assertNoEvents();
6989
6990 // Move to another window and release button, expect to drop item.
6991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6992 injectMotionEvent(mDispatcher,
6993 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
6994 .buttonState(0)
6995 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
6996 .x(150)
6997 .y(50))
6998 .build()))
6999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7000 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7001 mWindow->assertNoEvents();
7002 mSecondWindow->assertNoEvents();
7003 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7004
7005 // nothing to the window.
7006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7007 injectMotionEvent(mDispatcher,
7008 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
7009 .buttonState(0)
7010 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
7011 .x(150)
7012 .y(50))
7013 .build()))
7014 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7015 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7016 mWindow->assertNoEvents();
7017 mSecondWindow->assertNoEvents();
7018}
7019
Arthur Hung54745652022-04-20 07:17:41 +00007020TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007021 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08007022
7023 // Set second window invisible.
7024 mSecondWindow->setVisible(false);
7025 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
7026
7027 // Move on window.
7028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7029 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7030 ADISPLAY_ID_DEFAULT, {50, 50}))
7031 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7032 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7033 mWindow->consumeDragEvent(false, 50, 50);
7034 mSecondWindow->assertNoEvents();
7035
7036 // Move to another window.
7037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7038 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7039 ADISPLAY_ID_DEFAULT, {150, 50}))
7040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7041 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7042 mWindow->consumeDragEvent(true, 150, 50);
7043 mSecondWindow->assertNoEvents();
7044
7045 // drop to another window.
7046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7047 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7048 {150, 50}))
7049 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7050 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7051 mFakePolicy->assertDropTargetEquals(nullptr);
7052 mWindow->assertNoEvents();
7053 mSecondWindow->assertNoEvents();
7054}
7055
Arthur Hung54745652022-04-20 07:17:41 +00007056TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007057 // Ensure window could track pointerIds if it didn't support split touch.
7058 mWindow->setPreventSplitting(true);
7059
Arthur Hung54745652022-04-20 07:17:41 +00007060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7061 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7062 {50, 50}))
7063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7064 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7065
7066 const MotionEvent secondFingerDownEvent =
7067 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7068 .displayId(ADISPLAY_ID_DEFAULT)
7069 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7070 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7071 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(75).y(50))
7072 .build();
7073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7074 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7075 InputEventInjectionSync::WAIT_FOR_RESULT))
7076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7077 mWindow->consumeMotionPointerDown(1 /* pointerIndex */);
7078
7079 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007080 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00007081}
7082
7083TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
7084 // First down on second window.
7085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7086 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7087 {150, 50}))
7088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7089
7090 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7091
7092 // Second down on first window.
7093 const MotionEvent secondFingerDownEvent =
7094 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7095 .displayId(ADISPLAY_ID_DEFAULT)
7096 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7097 .pointer(
7098 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7099 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7100 .build();
7101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7102 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7103 InputEventInjectionSync::WAIT_FOR_RESULT))
7104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7105 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7106
7107 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007108 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00007109
7110 // Move on window.
7111 const MotionEvent secondFingerMoveEvent =
7112 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7113 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7114 .pointer(
7115 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7116 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7117 .build();
7118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7119 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
7120 InputEventInjectionSync::WAIT_FOR_RESULT));
7121 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7122 mWindow->consumeDragEvent(false, 50, 50);
7123 mSecondWindow->consumeMotionMove();
7124
7125 // Release the drag pointer should perform drop.
7126 const MotionEvent secondFingerUpEvent =
7127 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7128 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7129 .pointer(
7130 PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7131 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7132 .build();
7133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7134 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
7135 InputEventInjectionSync::WAIT_FOR_RESULT));
7136 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7137 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
7138 mWindow->assertNoEvents();
7139 mSecondWindow->consumeMotionMove();
7140}
7141
Arthur Hung3915c1f2022-05-31 07:17:17 +00007142TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007143 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00007144
7145 // Update window of second display.
7146 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007147 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00007148 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
7149
7150 // Let second display has a touch state.
7151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7152 injectMotionEvent(mDispatcher,
7153 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7154 AINPUT_SOURCE_TOUCHSCREEN)
7155 .displayId(SECOND_DISPLAY_ID)
7156 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7157 .x(100)
7158 .y(100))
7159 .build()));
7160 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
7161 SECOND_DISPLAY_ID, 0 /* expectedFlag */);
7162 // Update window again.
7163 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
7164
7165 // Move on window.
7166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7167 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7168 ADISPLAY_ID_DEFAULT, {50, 50}))
7169 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7170 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7171 mWindow->consumeDragEvent(false, 50, 50);
7172 mSecondWindow->assertNoEvents();
7173
7174 // Move to another window.
7175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7176 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7177 ADISPLAY_ID_DEFAULT, {150, 50}))
7178 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7179 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7180 mWindow->consumeDragEvent(true, 150, 50);
7181 mSecondWindow->consumeDragEvent(false, 50, 50);
7182
7183 // drop to another window.
7184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7185 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7186 {150, 50}))
7187 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7188 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7189 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7190 mWindow->assertNoEvents();
7191 mSecondWindow->assertNoEvents();
7192}
7193
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007194TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
7195 startDrag(true, AINPUT_SOURCE_MOUSE);
7196 // Move on window.
7197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7198 injectMotionEvent(mDispatcher,
7199 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
7200 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
7201 .pointer(PointerBuilder(MOUSE_POINTER_ID,
7202 AMOTION_EVENT_TOOL_TYPE_MOUSE)
7203 .x(50)
7204 .y(50))
7205 .build()))
7206 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7207 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7208 mWindow->consumeDragEvent(false, 50, 50);
7209 mSecondWindow->assertNoEvents();
7210
7211 // Move to another window.
7212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7213 injectMotionEvent(mDispatcher,
7214 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
7215 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
7216 .pointer(PointerBuilder(MOUSE_POINTER_ID,
7217 AMOTION_EVENT_TOOL_TYPE_MOUSE)
7218 .x(150)
7219 .y(50))
7220 .build()))
7221 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7222 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7223 mWindow->consumeDragEvent(true, 150, 50);
7224 mSecondWindow->consumeDragEvent(false, 50, 50);
7225
7226 // drop to another window.
7227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7228 injectMotionEvent(mDispatcher,
7229 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
7230 .buttonState(0)
7231 .pointer(PointerBuilder(MOUSE_POINTER_ID,
7232 AMOTION_EVENT_TOOL_TYPE_MOUSE)
7233 .x(150)
7234 .y(50))
7235 .build()))
7236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7237 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7238 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7239 mWindow->assertNoEvents();
7240 mSecondWindow->assertNoEvents();
7241}
7242
Vishnu Nair062a8672021-09-03 16:07:44 -07007243class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
7244
7245TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
7246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007247 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
7248 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007249 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07007250 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7251 window->setFocusable(true);
7252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
7253 setFocusedWindow(window);
7254 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7255
7256 // With the flag set, window should not get any input
7257 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
7258 mDispatcher->notifyKey(&keyArgs);
7259 window->assertNoEvents();
7260
7261 NotifyMotionArgs motionArgs =
7262 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7263 ADISPLAY_ID_DEFAULT);
7264 mDispatcher->notifyMotion(&motionArgs);
7265 window->assertNoEvents();
7266
7267 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007268 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007269 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
7270
7271 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
7272 mDispatcher->notifyKey(&keyArgs);
7273 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
7274
7275 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7276 ADISPLAY_ID_DEFAULT);
7277 mDispatcher->notifyMotion(&motionArgs);
7278 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7279 window->assertNoEvents();
7280}
7281
7282TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
7283 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
7284 std::make_shared<FakeApplicationHandle>();
7285 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007286 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
7287 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07007288 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
7289 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007290 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007291 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007292 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
7293 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007294 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07007295 window->setOwnerInfo(222, 222);
7296 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7297 window->setFocusable(true);
7298 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7299 setFocusedWindow(window);
7300 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7301
7302 // With the flag set, window should not get any input
7303 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
7304 mDispatcher->notifyKey(&keyArgs);
7305 window->assertNoEvents();
7306
7307 NotifyMotionArgs motionArgs =
7308 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7309 ADISPLAY_ID_DEFAULT);
7310 mDispatcher->notifyMotion(&motionArgs);
7311 window->assertNoEvents();
7312
7313 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007314 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007315 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7316
7317 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
7318 mDispatcher->notifyKey(&keyArgs);
7319 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
7320
7321 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7322 ADISPLAY_ID_DEFAULT);
7323 mDispatcher->notifyMotion(&motionArgs);
7324 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7325 window->assertNoEvents();
7326}
7327
7328TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
7329 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
7330 std::make_shared<FakeApplicationHandle>();
7331 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007332 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
7333 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07007334 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
7335 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007336 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07007337 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007338 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
7339 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007340 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07007341 window->setOwnerInfo(222, 222);
7342 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7343 window->setFocusable(true);
7344 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
7345 setFocusedWindow(window);
7346 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
7347
7348 // With the flag set, window should not get any input
7349 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
7350 mDispatcher->notifyKey(&keyArgs);
7351 window->assertNoEvents();
7352
7353 NotifyMotionArgs motionArgs =
7354 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7355 ADISPLAY_ID_DEFAULT);
7356 mDispatcher->notifyMotion(&motionArgs);
7357 window->assertNoEvents();
7358
7359 // When the window is no longer obscured because it went on top, it should get input
7360 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
7361
7362 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
7363 mDispatcher->notifyKey(&keyArgs);
7364 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
7365
7366 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7367 ADISPLAY_ID_DEFAULT);
7368 mDispatcher->notifyMotion(&motionArgs);
7369 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7370 window->assertNoEvents();
7371}
7372
Antonio Kantekf16f2832021-09-28 04:39:20 +00007373class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
7374protected:
7375 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00007376 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00007377 sp<FakeWindowHandle> mWindow;
7378 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00007379 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00007380
7381 void SetUp() override {
7382 InputDispatcherTest::SetUp();
7383
7384 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00007385 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007386 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007387 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007388 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007389 mSecondWindow =
7390 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007391 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00007392 mThirdWindow =
7393 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
7394 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
7395 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007396
7397 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00007398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
7399 {SECOND_DISPLAY_ID, {mThirdWindow}}});
7400 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007401 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007402
Antonio Kantek15beb512022-06-13 22:35:41 +00007403 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00007404 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Antonio Kantek15beb512022-06-13 22:35:41 +00007405 WINDOW_UID, true /* hasPermission */,
7406 ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07007407 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
7408 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00007409 mThirdWindow->assertNoEvents();
7410 }
7411
7412 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
7413 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
7414 SECONDARY_WINDOW_UID, true /* hasPermission */,
7415 SECOND_DISPLAY_ID)) {
7416 mWindow->assertNoEvents();
7417 mSecondWindow->assertNoEvents();
7418 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07007419 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00007420 }
7421
Antonio Kantek15beb512022-06-13 22:35:41 +00007422 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
7423 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07007424 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
7425 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00007426 mWindow->consumeTouchModeEvent(inTouchMode);
7427 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00007428 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00007429 }
7430};
7431
Antonio Kantek26defcf2022-02-08 01:12:27 +00007432TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08007433 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00007434 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
7435 windowInfo.ownerPid, windowInfo.ownerUid,
7436 false /* hasPermission */);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007437}
7438
Antonio Kantek26defcf2022-02-08 01:12:27 +00007439TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
7440 const WindowInfo& windowInfo = *mWindow->getInfo();
7441 int32_t ownerPid = windowInfo.ownerPid;
7442 int32_t ownerUid = windowInfo.ownerUid;
7443 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
7444 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007445 ownerUid, false /*hasPermission*/,
7446 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00007447 mWindow->assertNoEvents();
7448 mSecondWindow->assertNoEvents();
7449}
7450
7451TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
7452 const WindowInfo& windowInfo = *mWindow->getInfo();
7453 int32_t ownerPid = windowInfo.ownerPid;
7454 int32_t ownerUid = windowInfo.ownerUid;
7455 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00007456 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
7457 ownerUid, true /*hasPermission*/);
Antonio Kantek26defcf2022-02-08 01:12:27 +00007458}
7459
Antonio Kantekf16f2832021-09-28 04:39:20 +00007460TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08007461 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00007462 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
7463 windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007464 true /*hasPermission*/, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00007465 mWindow->assertNoEvents();
7466 mSecondWindow->assertNoEvents();
7467}
7468
Antonio Kantek15beb512022-06-13 22:35:41 +00007469TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
7470 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
7471 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
7472 windowInfo.ownerPid, windowInfo.ownerUid,
7473 true /*hasPermission*/, SECOND_DISPLAY_ID));
7474 mWindow->assertNoEvents();
7475 mSecondWindow->assertNoEvents();
7476 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
7477}
7478
Antonio Kantek48710e42022-03-24 14:19:30 -07007479TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
7480 // Interact with the window first.
7481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
7482 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7483 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7484
7485 // Then remove focus.
7486 mWindow->setFocusable(false);
7487 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7488
7489 // Assert that caller can switch touch mode by owning one of the last interacted window.
7490 const WindowInfo& windowInfo = *mWindow->getInfo();
7491 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
7492 windowInfo.ownerPid, windowInfo.ownerUid,
Antonio Kanteka042c022022-07-06 16:51:07 -07007493 false /*hasPermission*/, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07007494}
7495
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007496class InputDispatcherSpyWindowTest : public InputDispatcherTest {
7497public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007498 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007499 std::shared_ptr<FakeApplicationHandle> application =
7500 std::make_shared<FakeApplicationHandle>();
7501 std::string name = "Fake Spy ";
7502 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007503 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
7504 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007505 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007506 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007507 return spy;
7508 }
7509
7510 sp<FakeWindowHandle> createForeground() {
7511 std::shared_ptr<FakeApplicationHandle> application =
7512 std::make_shared<FakeApplicationHandle>();
7513 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007514 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7515 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007516 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007517 return window;
7518 }
7519
7520private:
7521 int mSpyCount{0};
7522};
7523
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08007524using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007525/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007526 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
7527 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08007528TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
7529 ScopedSilentDeath _silentDeath;
7530
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007531 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08007532 spy->setTrustedOverlay(false);
7533 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
7534 ".* not a trusted overlay");
7535}
7536
7537/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007538 * Input injection into a display with a spy window but no foreground windows should succeed.
7539 */
7540TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007541 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007542 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
7543
7544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7545 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7546 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7547 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7548}
7549
7550/**
7551 * Verify the order in which different input windows receive events. The touched foreground window
7552 * (if there is one) should always receive the event first. When there are multiple spy windows, the
7553 * spy windows will receive the event according to their Z-order, where the top-most spy window will
7554 * receive events before ones belows it.
7555 *
7556 * Here, we set up a scenario with four windows in the following Z order from the top:
7557 * spy1, spy2, window, spy3.
7558 * We then inject an event and verify that the foreground "window" receives it first, followed by
7559 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
7560 * window.
7561 */
7562TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
7563 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007564 auto spy1 = createSpy();
7565 auto spy2 = createSpy();
7566 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007567 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
7568 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
7569 const size_t numChannels = channels.size();
7570
Michael Wright8e9a8562022-02-09 13:44:29 +00007571 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007572 if (!epollFd.ok()) {
7573 FAIL() << "Failed to create epoll fd";
7574 }
7575
7576 for (size_t i = 0; i < numChannels; i++) {
7577 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
7578 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
7579 FAIL() << "Failed to add fd to epoll";
7580 }
7581 }
7582
7583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7584 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7586
7587 std::vector<size_t> eventOrder;
7588 std::vector<struct epoll_event> events(numChannels);
7589 for (;;) {
7590 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
7591 (100ms).count());
7592 if (nFds < 0) {
7593 FAIL() << "Failed to call epoll_wait";
7594 }
7595 if (nFds == 0) {
7596 break; // epoll_wait timed out
7597 }
7598 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07007599 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07007600 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007601 channels[i]->consumeMotionDown();
7602 }
7603 }
7604
7605 // Verify the order in which the events were received.
7606 EXPECT_EQ(3u, eventOrder.size());
7607 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
7608 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
7609 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
7610}
7611
7612/**
7613 * A spy window using the NOT_TOUCHABLE flag does not receive events.
7614 */
7615TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
7616 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007617 auto spy = createSpy();
7618 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007619 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7620
7621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7622 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7624 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7625 spy->assertNoEvents();
7626}
7627
7628/**
7629 * A spy window will only receive gestures that originate within its touchable region. Gestures that
7630 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
7631 * to the window.
7632 */
7633TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
7634 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007635 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007636 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
7637 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7638
7639 // Inject an event outside the spy window's touchable region.
7640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7641 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7643 window->consumeMotionDown();
7644 spy->assertNoEvents();
7645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7646 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7648 window->consumeMotionUp();
7649 spy->assertNoEvents();
7650
7651 // Inject an event inside the spy window's touchable region.
7652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7653 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7654 {5, 10}))
7655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7656 window->consumeMotionDown();
7657 spy->consumeMotionDown();
7658}
7659
7660/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007661 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007662 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007663 */
7664TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
7665 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007666 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007667 auto spy = createSpy();
7668 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007669 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007670 spy->setFrame(Rect{0, 0, 20, 20});
7671 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7672
7673 // Inject an event outside the spy window's frame and touchable region.
7674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007675 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7676 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7678 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007679 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007680}
7681
7682/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007683 * Even when a spy window spans over multiple foreground windows, the spy should receive all
7684 * pointers that are down within its bounds.
7685 */
7686TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
7687 auto windowLeft = createForeground();
7688 windowLeft->setFrame({0, 0, 100, 200});
7689 auto windowRight = createForeground();
7690 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007691 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007692 spy->setFrame({0, 0, 200, 200});
7693 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
7694
7695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7696 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7697 {50, 50}))
7698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7699 windowLeft->consumeMotionDown();
7700 spy->consumeMotionDown();
7701
7702 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007703 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007704 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7705 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7706 .pointer(
7707 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7708 .build();
7709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7710 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7711 InputEventInjectionSync::WAIT_FOR_RESULT))
7712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7713 windowRight->consumeMotionDown();
7714 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
7715}
7716
7717/**
7718 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
7719 * the spy should receive the second pointer with ACTION_DOWN.
7720 */
7721TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
7722 auto window = createForeground();
7723 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007724 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007725 spyRight->setFrame({100, 0, 200, 200});
7726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
7727
7728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7729 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7730 {50, 50}))
7731 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7732 window->consumeMotionDown();
7733 spyRight->assertNoEvents();
7734
7735 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007736 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08007737 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7738 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7739 .pointer(
7740 PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
7741 .build();
7742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7743 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7744 InputEventInjectionSync::WAIT_FOR_RESULT))
7745 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7746 window->consumeMotionPointerDown(1 /*pointerIndex*/);
7747 spyRight->consumeMotionDown();
7748}
7749
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007750/**
7751 * The spy window should not be able to affect whether or not touches are split. Only the foreground
7752 * windows should be allowed to control split touch.
7753 */
7754TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007755 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007756 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007757 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007758 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007759
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007760 auto window = createForeground();
7761 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007762
7763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7764
7765 // First finger down, no window touched.
7766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7767 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7768 {100, 200}))
7769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7770 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7771 window->assertNoEvents();
7772
7773 // Second finger down on window, the window should receive touch down.
7774 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007775 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007776 .displayId(ADISPLAY_ID_DEFAULT)
7777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7778 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7779 .x(100)
7780 .y(200))
7781 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7782 .build();
7783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7784 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7785 InputEventInjectionSync::WAIT_FOR_RESULT))
7786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7787
7788 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7789 spy->consumeMotionPointerDown(1 /* pointerIndex */);
7790}
7791
7792/**
7793 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
7794 * do not receive key events.
7795 */
7796TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007797 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007798 spy->setFocusable(false);
7799
7800 auto window = createForeground();
7801 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7802 setFocusedWindow(window);
7803 window->consumeFocusEvent(true);
7804
7805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7806 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7807 window->consumeKeyDown(ADISPLAY_ID_NONE);
7808
7809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7810 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7811 window->consumeKeyUp(ADISPLAY_ID_NONE);
7812
7813 spy->assertNoEvents();
7814}
7815
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00007816using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
7817
7818/**
7819 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
7820 * are currently sent to any other windows - including other spy windows - will also be cancelled.
7821 */
7822TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
7823 auto window = createForeground();
7824 auto spy1 = createSpy();
7825 auto spy2 = createSpy();
7826 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
7827
7828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7829 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7831 window->consumeMotionDown();
7832 spy1->consumeMotionDown();
7833 spy2->consumeMotionDown();
7834
7835 // Pilfer pointers from the second spy window.
7836 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
7837 spy2->assertNoEvents();
7838 spy1->consumeMotionCancel();
7839 window->consumeMotionCancel();
7840
7841 // The rest of the gesture should only be sent to the second spy window.
7842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7843 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7844 ADISPLAY_ID_DEFAULT))
7845 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7846 spy2->consumeMotionMove();
7847 spy1->assertNoEvents();
7848 window->assertNoEvents();
7849}
7850
7851/**
7852 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
7853 * in the middle of the gesture.
7854 */
7855TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
7856 auto window = createForeground();
7857 auto spy = createSpy();
7858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7859
7860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7861 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7863 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7864 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7865
7866 window->releaseChannel();
7867
7868 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7869
7870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7871 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
7872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7873 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7874}
7875
7876/**
7877 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
7878 * the spy, but not to any other windows.
7879 */
7880TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
7881 auto spy = createSpy();
7882 auto window = createForeground();
7883
7884 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7885
7886 // First finger down on the window and the spy.
7887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7888 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7889 {100, 200}))
7890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7891 spy->consumeMotionDown();
7892 window->consumeMotionDown();
7893
7894 // Spy window pilfers the pointers.
7895 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7896 window->consumeMotionCancel();
7897
7898 // Second finger down on the window and spy, but the window should not receive the pointer down.
7899 const MotionEvent secondFingerDownEvent =
7900 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7901 .displayId(ADISPLAY_ID_DEFAULT)
7902 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7903 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7904 .x(100)
7905 .y(200))
7906 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7907 .build();
7908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7909 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7910 InputEventInjectionSync::WAIT_FOR_RESULT))
7911 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7912
7913 spy->consumeMotionPointerDown(1 /*pointerIndex*/);
7914
7915 // Third finger goes down outside all windows, so injection should fail.
7916 const MotionEvent thirdFingerDownEvent =
7917 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7918 .displayId(ADISPLAY_ID_DEFAULT)
7919 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7920 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7921 .x(100)
7922 .y(200))
7923 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7924 .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
7925 .build();
7926 ASSERT_EQ(InputEventInjectionResult::FAILED,
7927 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
7928 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007929 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00007930
7931 spy->assertNoEvents();
7932 window->assertNoEvents();
7933}
7934
7935/**
7936 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
7937 */
7938TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
7939 auto spy = createSpy();
7940 spy->setFrame(Rect(0, 0, 100, 100));
7941 auto window = createForeground();
7942 window->setFrame(Rect(0, 0, 200, 200));
7943
7944 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
7945
7946 // First finger down on the window only
7947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7948 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7949 {150, 150}))
7950 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7951 window->consumeMotionDown();
7952
7953 // Second finger down on the spy and window
7954 const MotionEvent secondFingerDownEvent =
7955 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7956 .displayId(ADISPLAY_ID_DEFAULT)
7957 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7958 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7959 .x(150)
7960 .y(150))
7961 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7962 .build();
7963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7964 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7965 InputEventInjectionSync::WAIT_FOR_RESULT))
7966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7967 spy->consumeMotionDown();
7968 window->consumeMotionPointerDown(1);
7969
7970 // Third finger down on the spy and window
7971 const MotionEvent thirdFingerDownEvent =
7972 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7973 .displayId(ADISPLAY_ID_DEFAULT)
7974 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
7975 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
7976 .x(150)
7977 .y(150))
7978 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
7979 .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7980 .build();
7981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7982 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
7983 InputEventInjectionSync::WAIT_FOR_RESULT))
7984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7985 spy->consumeMotionPointerDown(1);
7986 window->consumeMotionPointerDown(2);
7987
7988 // Spy window pilfers the pointers.
7989 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
7990 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7991 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7992
7993 spy->assertNoEvents();
7994 window->assertNoEvents();
7995}
7996
7997/**
7998 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
7999 * other windows should be canceled. If this results in the cancellation of all pointers for some
8000 * window, then that window should receive ACTION_CANCEL.
8001 */
8002TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
8003 auto spy = createSpy();
8004 spy->setFrame(Rect(0, 0, 100, 100));
8005 auto window = createForeground();
8006 window->setFrame(Rect(0, 0, 200, 200));
8007
8008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8009
8010 // First finger down on both spy and window
8011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8012 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8013 {10, 10}))
8014 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8015 window->consumeMotionDown();
8016 spy->consumeMotionDown();
8017
8018 // Second finger down on the spy and window
8019 const MotionEvent secondFingerDownEvent =
8020 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8021 .displayId(ADISPLAY_ID_DEFAULT)
8022 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
8023 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
8024 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8025 .build();
8026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8027 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8028 InputEventInjectionSync::WAIT_FOR_RESULT))
8029 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8030 spy->consumeMotionPointerDown(1);
8031 window->consumeMotionPointerDown(1);
8032
8033 // Spy window pilfers the pointers.
8034 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8035 window->consumeMotionCancel();
8036
8037 spy->assertNoEvents();
8038 window->assertNoEvents();
8039}
8040
8041/**
8042 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
8043 * be sent to other windows
8044 */
8045TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
8046 auto spy = createSpy();
8047 spy->setFrame(Rect(0, 0, 100, 100));
8048 auto window = createForeground();
8049 window->setFrame(Rect(0, 0, 200, 200));
8050
8051 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8052
8053 // First finger down on both window and spy
8054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8055 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8056 {10, 10}))
8057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8058 window->consumeMotionDown();
8059 spy->consumeMotionDown();
8060
8061 // Spy window pilfers the pointers.
8062 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8063 window->consumeMotionCancel();
8064
8065 // Second finger down on the window only
8066 const MotionEvent secondFingerDownEvent =
8067 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8068 .displayId(ADISPLAY_ID_DEFAULT)
8069 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
8070 .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
8071 .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
8072 .x(150)
8073 .y(150))
8074 .build();
8075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8076 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8077 InputEventInjectionSync::WAIT_FOR_RESULT))
8078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8079 window->consumeMotionDown();
8080 window->assertNoEvents();
8081
8082 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
8083 spy->consumeMotionMove();
8084 spy->assertNoEvents();
8085}
8086
Prabir Pradhand65552b2021-10-07 11:23:50 -07008087class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
8088public:
8089 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
8090 std::shared_ptr<FakeApplicationHandle> overlayApplication =
8091 std::make_shared<FakeApplicationHandle>();
8092 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008093 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
8094 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07008095 overlay->setFocusable(false);
8096 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008097 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008098 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07008099 overlay->setTrustedOverlay(true);
8100
8101 std::shared_ptr<FakeApplicationHandle> application =
8102 std::make_shared<FakeApplicationHandle>();
8103 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008104 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
8105 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07008106 window->setFocusable(true);
8107 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07008108
8109 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8110 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
8111 setFocusedWindow(window);
8112 window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
8113 return {std::move(overlay), std::move(window)};
8114 }
8115
8116 void sendFingerEvent(int32_t action) {
8117 NotifyMotionArgs motionArgs =
8118 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
8119 ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
8120 mDispatcher->notifyMotion(&motionArgs);
8121 }
8122
8123 void sendStylusEvent(int32_t action) {
8124 NotifyMotionArgs motionArgs =
8125 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
8126 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
8127 motionArgs.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
8128 mDispatcher->notifyMotion(&motionArgs);
8129 }
8130};
8131
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008132using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
8133
8134TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
8135 ScopedSilentDeath _silentDeath;
8136
Prabir Pradhand65552b2021-10-07 11:23:50 -07008137 auto [overlay, window] = setupStylusOverlayScenario();
8138 overlay->setTrustedOverlay(false);
8139 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
8140 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
8141 ".* not a trusted overlay");
8142}
8143
8144TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
8145 auto [overlay, window] = setupStylusOverlayScenario();
8146 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
8147
8148 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
8149 overlay->consumeMotionDown();
8150 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
8151 overlay->consumeMotionUp();
8152
8153 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
8154 window->consumeMotionDown();
8155 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
8156 window->consumeMotionUp();
8157
8158 overlay->assertNoEvents();
8159 window->assertNoEvents();
8160}
8161
8162TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
8163 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008164 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07008165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
8166
8167 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
8168 overlay->consumeMotionDown();
8169 window->consumeMotionDown();
8170 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
8171 overlay->consumeMotionUp();
8172 window->consumeMotionUp();
8173
8174 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
8175 window->consumeMotionDown();
8176 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
8177 window->consumeMotionUp();
8178
8179 overlay->assertNoEvents();
8180 window->assertNoEvents();
8181}
8182
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00008183/**
8184 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
8185 * The scenario is as follows:
8186 * - The stylus interceptor overlay is configured as a spy window.
8187 * - The stylus interceptor spy receives the start of a new stylus gesture.
8188 * - It pilfers pointers and then configures itself to no longer be a spy.
8189 * - The stylus interceptor continues to receive the rest of the gesture.
8190 */
8191TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
8192 auto [overlay, window] = setupStylusOverlayScenario();
8193 overlay->setSpy(true);
8194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
8195
8196 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
8197 overlay->consumeMotionDown();
8198 window->consumeMotionDown();
8199
8200 // The interceptor pilfers the pointers.
8201 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
8202 window->consumeMotionCancel();
8203
8204 // The interceptor configures itself so that it is no longer a spy.
8205 overlay->setSpy(false);
8206 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
8207
8208 // It continues to receive the rest of the stylus gesture.
8209 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
8210 overlay->consumeMotionMove();
8211 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
8212 overlay->consumeMotionUp();
8213
8214 window->assertNoEvents();
8215}
8216
Prabir Pradhan5735a322022-04-11 17:23:34 +00008217struct User {
8218 int32_t mPid;
8219 int32_t mUid;
8220 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
8221 std::unique_ptr<InputDispatcher>& mDispatcher;
8222
8223 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
8224 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
8225
8226 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
8227 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
8228 ADISPLAY_ID_DEFAULT, {100, 200},
8229 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8230 AMOTION_EVENT_INVALID_CURSOR_POSITION},
8231 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
8232 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
8233 }
8234
8235 InputEventInjectionResult injectTargetedKey(int32_t action) const {
8236 return inputdispatcher::injectKey(mDispatcher, action, 0 /* repeatCount*/, ADISPLAY_ID_NONE,
8237 InputEventInjectionSync::WAIT_FOR_RESULT,
8238 INJECT_EVENT_TIMEOUT, false /*allowKeyRepeat*/, {mUid},
8239 mPolicyFlags);
8240 }
8241
8242 sp<FakeWindowHandle> createWindow() const {
8243 std::shared_ptr<FakeApplicationHandle> overlayApplication =
8244 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008245 sp<FakeWindowHandle> window =
8246 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
8247 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00008248 window->setOwnerInfo(mPid, mUid);
8249 return window;
8250 }
8251};
8252
8253using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
8254
8255TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
8256 auto owner = User(mDispatcher, 10, 11);
8257 auto window = owner.createWindow();
8258 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8259
8260 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8261 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8262 window->consumeMotionDown();
8263
8264 setFocusedWindow(window);
8265 window->consumeFocusEvent(true);
8266
8267 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8268 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
8269 window->consumeKeyDown(ADISPLAY_ID_NONE);
8270}
8271
8272TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
8273 auto owner = User(mDispatcher, 10, 11);
8274 auto window = owner.createWindow();
8275 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8276
8277 auto rando = User(mDispatcher, 20, 21);
8278 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
8279 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8280
8281 setFocusedWindow(window);
8282 window->consumeFocusEvent(true);
8283
8284 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
8285 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
8286 window->assertNoEvents();
8287}
8288
8289TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
8290 auto owner = User(mDispatcher, 10, 11);
8291 auto window = owner.createWindow();
8292 auto spy = owner.createWindow();
8293 spy->setSpy(true);
8294 spy->setTrustedOverlay(true);
8295 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8296
8297 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8298 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8299 spy->consumeMotionDown();
8300 window->consumeMotionDown();
8301}
8302
8303TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
8304 auto owner = User(mDispatcher, 10, 11);
8305 auto window = owner.createWindow();
8306
8307 auto rando = User(mDispatcher, 20, 21);
8308 auto randosSpy = rando.createWindow();
8309 randosSpy->setSpy(true);
8310 randosSpy->setTrustedOverlay(true);
8311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
8312
8313 // The event is targeted at owner's window, so injection should succeed, but the spy should
8314 // not receive the event.
8315 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8316 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8317 randosSpy->assertNoEvents();
8318 window->consumeMotionDown();
8319}
8320
8321TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
8322 auto owner = User(mDispatcher, 10, 11);
8323 auto window = owner.createWindow();
8324
8325 auto rando = User(mDispatcher, 20, 21);
8326 auto randosSpy = rando.createWindow();
8327 randosSpy->setSpy(true);
8328 randosSpy->setTrustedOverlay(true);
8329 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
8330
8331 // A user that has injection permission can inject into any window.
8332 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8333 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8334 ADISPLAY_ID_DEFAULT));
8335 randosSpy->consumeMotionDown();
8336 window->consumeMotionDown();
8337
8338 setFocusedWindow(randosSpy);
8339 randosSpy->consumeFocusEvent(true);
8340
8341 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
8342 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
8343 window->assertNoEvents();
8344}
8345
8346TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
8347 auto owner = User(mDispatcher, 10, 11);
8348 auto window = owner.createWindow();
8349
8350 auto rando = User(mDispatcher, 20, 21);
8351 auto randosWindow = rando.createWindow();
8352 randosWindow->setFrame(Rect{-10, -10, -5, -5});
8353 randosWindow->setWatchOutsideTouch(true);
8354 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
8355
8356 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
8357 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
8358 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
8359 window->consumeMotionDown();
8360 randosWindow->consumeMotionOutside();
8361}
8362
Garfield Tane84e6f92019-08-29 17:28:41 -07008363} // namespace android::inputdispatcher